はじめに
C++やJSONを扱うことが多いのですが、とうとうC++でJSONをパースする必要に迫られそうなので
予習がてらに有名なC++のJSONパーサのひとつであるpicojsonをためしてみました。
なぜ最初にpicojsonをためしてみたか
C++のJSONパーサで聞いたことあるライブラリといえばpicojsonとrapidjson、それにboost::property_treeだったのですが、
調べたところ
- picojsonが一番簡単そう
- 今回は速度を重視しない
- boost::property_treeは木構造を汎用的に扱う管理ライブラリであり、XMLやJSONに対して統一的なアクセス方法を提供するためのもの
の3点からpicojsonがいいかなと思いました。
他2つもよさそうですが触るのは次の機会にします。
コードはこんな感じ
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <iterator>
#include "picojson.h"
int main(void)
{
// JSONデータの読み込み。
std::ifstream ifs("test.json", std::ios::in);
if (ifs.fail()) {
std::cerr << "failed to read test.json" << std::endl;
return 1;
}
const std::string json((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
ifs.close();
// JSONデータを解析する。
picojson::value v;
const std::string err = picojson::parse(v, json);
if (err.empty() == false) {
std::cerr << err << std::endl;
return 2;
}
std::cout << "いったんすべてを出力してみる。" << std::endl;
std::cout << v << std::endl;
std::cout << std::endl;
std::cout << "パースされたデータをのぞいてみる。" << std::endl;
picojson::object& obj = v.get<picojson::object>();
std::cout << "string: " << obj["string"].get<std::string>() << std::endl;
std::cout << "number_double: " << obj["number_double"].get<double>() << std::endl;
std::cout << "number_integer: " << obj["number_integer"].get<double>() << std::endl;
std::cout << "boolean_true: " << std::boolalpha << obj["boolean_true"].get<bool>() << std::endl;
std::cout << "boolean_false: "<< std::boolalpha << obj["boolean_false"].get<bool>() << std::endl;
std::cout << "array: ";
picojson::array& ary = obj["array"].get<picojson::array>();
for (const auto& e : ary) { // vectorをrange-based-forでまわしている。
std::cout << e.get<std::string>() << " ";
}
std::cout << "\n\n";
std::cout << "ループをまわしてみる。" << std::endl;
for (const auto& p : obj) { // mapをrange-based-forでまわしている。
std::cout << p.first << ": " << p.second.to_str() << std::endl;
}
return 0;
}
入力(test.json)
{
"string": "テスト0",
"number_double": 123.456,
"number_integer": 123456,
"boolean_true": true,
"boolean_false": false,
"array": [
"array_elem0",
"array_elem1",
"array_elem2"
]
}
出力結果
いったんすべてを出力してみる。
{"array":["array_elem0","array_elem1","array_elem2"],"boolean_false":false,"boolean_true":true,"number_double":123.456,"number_integer":123456,"string":"テスト0"}
パースされたデータをのぞいてみる。
string: テスト0
number_double: 123.456
number_integer: 123456
boolean_true: true
boolean_false: false
array: array_elem0 array_elem1 array_elem2
ループをまわしてみる。
array: array
boolean_false: false
boolean_true: true
number_double: 123.456
number_integer: 123456
string: テスト0
感想
STLフレンドリーをうたうだけあってとっかかりやすかったです。
実務では最後のループを再帰的に展開する感じになるのかな?
JSONではintやdoubleという分類はなく、どちらもnumberとなるのでget<double>()で取得できるようです。
参考
https://github.com/kazuho/picojson
https://qiita.com/voluntas/items/48ec1b9dc781a1571545
https://www.mk-mode.com/octopress/2014/11/15/cpp-parse-json-by-picojson/