もくじ
https://tera1707.com/entry/2022/02/06/144447
やりたいこと
人に聞いたところによると、nlohmann.json
というライブラリがよいらしい。やってみる。
やったこと
準備
VisualStudio2022で、C++のプロジェクトを作る。
そのプロジェクトで「nugetパッケージの管理」を選んで、パッケージ管理画面を開く。
検索窓で「nlohmann」と入れると、nlohmann.json
が出てくるので、それを選択する。
※2024/07/11時点では「3.11.2」が最新の様子。
パッケージをインストールしたら、コードに、下記のように#include <nlohmann/json.hpp>
を追加する。
#include <iostream> #include <nlohmann/json.hpp>//★コレ int main() { }
そうすると、とりあえずnlohmann.json
が使えるようになる。
jsonファイルを読み込む
まずは、下記のコードを書いて実行してみた。
#include <iostream> #include <fstream> #include <nlohmann/json.hpp> int main() { // ファイルからjsonを読み込み std::ifstream f("C:\\temp\\testjson.json"); nlohmann::json data = nlohmann::json::parse(f); std::cout << "■nlohmann::json をそのまま出力" << std::endl; std::cout << data << std::endl; std::cout << "-----------------" << std::endl; std::cout << "■dump(4)で人間に見やすく整形して出力" << std::endl; std::cout << data.dump(4) << std::endl; std::cout << "-----------------" << std::endl; std::cout << "■特定の値だけを取る" << std::endl; std::cout << data["pi"] << std::endl; // std::strinとして値を取る std::string asStdString = data["name"].get<std::string>(); // doubleとして値を取る double asDouble = data["pi"].get<double>(); // 数値であるはずの値をstd::stringで取ろうとすると、例外が出る //std::string asStdStringError = data["pi"].get<std::string>(); }
出力結果
■nlohmann::json をそのまま出力 {"answer":{"everything":42},"happy":true,"list":[1,0,2],"name":"Niels","nothing":null,"object":{"currency":"USD","value":42.99},"pi":3.141} ----------------- ■dump(4)で人間に見やすく整形して出力 { "answer": { "everything": 42 }, "happy": true, "list": [ 1, 0, 2 ], "name": "Niels", "nothing": null, "object": { "currency": "USD", "value": 42.99 }, "pi": 3.141 } ----------------- ■特定の値だけを取る 3.141
※↑のコードの「数値であるはずの値をstd::stringで取ろうとすると、例外が出る」の部分のコメントを外して実行すると、下記の例外が起きる。
j.type_name()
の値を見ると、「number」になっている。
doubleであるべき値をstd::stringに変換しようとして、例外を起こしていると思われる。
json文字列⇔データクラスの変換
json文字列を読み込んで、データ保存用クラスに入れたり、
データ保存用クラスからjson文字列に直したりする。
下記で言うと、person
クラスが、データ用クラス。
#include <iostream> #include <fstream> #include <nlohmann/json.hpp> // a simple struct to model a person struct person { std::string name; std::string address; int age; }; void to_json(nlohmann::json& j, const person& p) { j = nlohmann::json{ {"name", p.name}, {"address", p.address}, {"age", p.age} }; } void from_json(const nlohmann::json& j, person& p) { j.at("name").get_to(p.name); j.at("address").get_to(p.address); j.at("age").get_to(p.age); } int main() { // jsonデータを入れるクラスを構築してから person p{ "Ned Flanders", "744 Evergreen Terrace", 60 }; // それをjsonクラスに入れると、勝手にto_json()を実行してjsonクラスを作ってくれる nlohmann::json j = p; std::cout << j.dump() << std::endl; //--------------- // jsonクラスからデータのクラスに変換(get)すると、勝手にfrom_json()を実行してデータクラスを作ってくれる auto p2 = j.get<person>(); }
json文字列をファイルに書き出し
作った文字列をファイルに書き込む。
#include <iostream> #include <fstream> #include <nlohmann/json.hpp> // a simple struct to model a person struct person { std::string name; std::string address; int age; }; void to_json(nlohmann::json& j, const person& p) { j = nlohmann::json{ {"name", p.name}, {"address", p.address}, {"age", p.age} }; } void from_json(const nlohmann::json& j, person& p) { j.at("name").get_to(p.name); j.at("address").get_to(p.address); j.at("age").get_to(p.age); } int main() { // json文字列を作成 person p{ "Ned Flanders", "744 Evergreen Terrace", 60 }; nlohmann::json j = p; // ファイルに書き出し std::ofstream f("C:\\temp\\testoutjson.json"); auto str = j.dump(4); auto len = str.length(); f.write(str.c_str(), len); }
参考
公式ページ
https://github.com/nlohmann/json
導入の仕方
https://json.nlohmann.me/integration/
使い方ざっくり
https://json.nlohmann.me/features/arbitrary_types/
APIリファレンス
https://json.nlohmann.me/api/basic_json/
ファイルの読み書き