おなじみC/C++から使えるJSONライブラリを紹介するコーナー。まずは過去のまとめ。
- ヘッダファイルだけでC++から使えるJSONパーサ「picojson」が凄い!
- 何も見ずにC++でjsonパーサが書けるか試してみた。
- C言語から使えるJSONパーサ、JSMNを試してみた。
- 僕がboost::asioとboost::property_treeを使いHTTPプロキシ環境下で非同期にGoogle Search APIから検索するまでにやった、たった一つの事。
- C言語から使えるJSONパーサ、parson が思った以上に良い仕事をしている。
- 最速と言われる JSON パーサ「rapidjson」が本当に爆速なのか試してみた。
- C言語から使えるJSONパーサ、jansson がとても直感的で良い
- C++ の JSON ライブラリ json11 は initializer_list が綺麗。
僕は C++ では STL が好きなので JSON をパースした後の構造も、std::map
や std::vector
で文字列も std::string
なのが好きです。なので picojson をひたすら使ってきましたが、picojson と同じ様に STL フレンドリな JSON ライブラリが ujson(μjson) です。
awangk / ujson — Bitbucket
https://bitbucket.org/awangk/ujson
特徴は以下の通り。
- 単純な API で小さなライブラリ
- 小綺麗なフォーマットでの JSON 出力
- UTF-8 を扱える速いパーサ
- 自由なライセンス
- C++11 フレンドリ
μjson は MIT ライセンスで提供されています。ただし double の変換(IEEE double)に v8 でも使われている double-conversion というライブラリを使用しており、その部分については double-conversion のライセンスに委ねられます。
double の変換を行うという事で、つまり Bignum が扱えます。picojson はヘッダオンリーですが、ujson はビルド済みライブラリをリンクしてビルドします。
#include <iostream>
#include <string>
#include <algorithm>
#include <ujson.hpp>
struct book_t {
std::string title;
std::vector<std::string> authors;
int year;
};
book_t
make_book(ujson::value v) {
if (!v.is_object())
throw std::invalid_argument("object expected for make_book");
book_t book;
std::vector<std::pair<std::string, ujson::value>> object =
object_cast(std::move(v));
auto it = find(object, "title");
if (it == object.end() || !it->second.is_string())
throw std::invalid_argument("'title' with type string not found");
book.title = string_cast(std::move(it->second));
it = find(object, "authors");
if (it == object.end() || !it->second.is_array())
throw std::invalid_argument("'authors' with type array not found");
std::vector<ujson::value> array = array_cast(std::move(it->second));
book.authors.reserve(array.size());
for (auto it = array.begin(); it != array.end(); ++it) {
if (!it->is_string())
throw std::invalid_argument("'authors' must be array of strings");
book.authors.push_back(string_cast(std::move(*it)));
}
it = find(object, "year");
if (it == object.end() || !it->second.is_number())
throw std::invalid_argument("'year' with type number not found");
book.year = int32_cast(it->second);
return book;
}
int
main(int argc, char* argv[]) {
auto v = ujson::parse(R"(
{
"title":"foo",
"authors":["bar", "baz"],
"year": 123
}
)");
auto t = make_book(v);
std::cout << "title:" << t.title << std::endl;
std::for_each(t.authors.begin(), t.authors.end(), [&](std::string& x) {
std::cout << "author:" << x << std::endl;
});
std::cout << "year:" << t.year << std::endl;
return 0;
}
オブジェクトにキーが存在した場合に find でイテレータを戻してくれるのでかなりスッキリ書けます。