C++のJSONパーサ『picojson』をためしてみました。

# はじめに
C++やJSONを扱うことが多いのですが、とうとうC++でJSONをパースする必要に迫られそうなので
予習がてらに有名なC++のJSONパーサのひとつであるpicojsonをためしてみました。

# なぜ最初にpicojsonをためしてみたか
C++のJSONパーサで聞いたことあるライブラリといえばpicojsonとrapidjson、それにboost::property_treeだったのですが、
調べたところ

1. picojsonが一番簡単そう
2. 今回は速度を重視しない
3. boost::property_treeは木構造を汎用的に扱う管理ライブラリであり、XMLやJSONに対して統一的なアクセス方法を提供するためのもの

の３点からpicojsonがいいかなと思いました。
他２つもよさそうですが触るのは次の機会にします。

# コードはこんな感じ
```c++
#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;
}
```

```json:入力(test.json)
{
    "string": "テスト0",
    "number_double": 123.456,
    "number_integer": 123456,
    "boolean_true": true,
    "boolean_false": false,
    "array": [
         "array_elem0",
         "array_elem1",
         "array_elem2"
    ]
}
```


```txt:出力結果
いったんすべてを出力してみる。
{"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/