備忘録

備忘録

C++でJSONを扱う方法

Ⅰ. はじめに

タイトルの通り「C++JSONを扱う方法」です。

ライブラリは cereal を利用します。
cereal は JSON 出力だけでなく、XMLやバイナリ出力にも対応しています。

Ⅱ. やり方

1. vcpkg で cereal をインストールする
vcpkg install cereal
2. サンプルプログラムを書く
#include <iostream>
#include <fstream>
#include <map>
#include <cereal/types/map.hpp>
#include <cereal/types/string.hpp>
#include <cereal/archives/json.hpp>

struct Person
{
  int32_t id;
  std::string name;
  std::map<uint32_t, std::string> items;

  template<class Archive>
  void serialize(Archive& archive)
  {
    archive(CEREAL_NVP(id), CEREAL_NVP(name), CEREAL_NVP(items));
  }
};

void serializeTest()
{
  Person x;
  x.id = 1;
  x.name = "田中";
  x.items.insert(std::make_pair(1, "りんご"));
  x.items.insert(std::make_pair(2, "バナナ"));

  // ファイル出力
  std::ofstream os("out.json", std::ios::out);
  cereal::JSONOutputArchive archiveFile(os);
  x.serialize(archiveFile);

  // 標準出力
  std::stringstream ss;
  {
    cereal::JSONOutputArchive archiveStdout(ss);
    x.serialize(archiveStdout);
  }
  std::cout << ss.str() << std::endl;
}

void deserializeTest()
{
  Person x;

  std::ifstream os("out.json", std::ios::in);
  cereal::JSONInputArchive archive(os);
  x.serialize(archive);

  std::cout << x.id << std::endl;
  std::cout << x.name << std::endl;
  for (auto item : x.items)
  {
    std::cout << item.first << "," << item.second << std::endl;
  }
}

int main()
{
  serializeTest();
  deserializeTest();
}

Ⅲ. 実行結果

{
    "id": 1,
    "name": "田中",
    "items": [
        {
            "key": 1,
            "value": "りんご"
        },
        {
            "key": 2,
            "value": "バナナ"
        }
    ]
}
1
田中
1,りんご
2,バナナ

Ⅳ. FAQ

整形されない形でJSONを出力できますか?

2019/11/19 時点で不可能です。
https://github.com/USCiLab/cereal/issues/308