LoginSignup
23
36

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-01-01

はじめに

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

なぜ最初にpicojsonをためしてみたか

C++のJSONパーサで聞いたことあるライブラリといえばpicojsonとrapidjson、それにboost::property_treeだったのですが、
調べたところ

  1. picojsonが一番簡単そう
  2. 今回は速度を重視しない
  3. 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/

23
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
36