罠があったらハマりたい。thinca です。嘘です。できればハマりたくありません。
さて、Boost Property Tree Library というのを使うと Boost で JSON を読み書きできるらしい!って噂を聞きました。
https://sites.google.com/site/boostjp/tips/json
ちょうどやりたいところだったので、Boost でできるのならこれ幸いと使ってみることに。
で、罠というのは、私がこのライブラリを JSON ライブラリとして使おうとしたところにあります。
実際のところ、「Boost Property Tree LibraryでJSONのデータを扱える」って言うと、半分正解で半分間違いです。
このライブラリはあくまで、まず Property Tree と言うデータ構造があり、ここに JSON を読み書きできるってだけです。なのでデータ構造としては Property Tree の流儀に合わせることになり、正確に JSON のデータとしては扱えない。例えば以下のような問題があります。
値は全て文字列
JSON には値に文字列やら数値やらあるんだけど、Property Tree に突っ込むと全て文字列になります。
ただし、取り出すときは pt.get
boost::property_tree::write_json() で書き出すと残念な感じになります。
ちなみにこの辺りのことはドキュメントに書いてある。
http://www.boost.org/doc/libs/1_47_0/doc/html/boost_propertytree/parsers.html#boost_propertytree.parsers.json_parser
ptree の value を boost::variant とかにしてどうにかできないのかなーとか考えたけど私にはよくわからなかった!
ルートは常にオブジェクト
ルートが配列の JSON を boost::property_tree::read_json() に渡すと、オブジェクトをよこせって怒られます。
#include <sstream> #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/json_parser.hpp> int main(int argc, const char *argv[]) { std::stringstream s("[1,2,3]"); boost::property_tree::ptree pt; boost::property_tree::read_json(s, pt); boost::property_tree::write_json(std::cout, pt, false); }
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::property_tree::json_parser::json_parser_error> >' what(): <unspecified file>(1): expected object
pretty = false で出力がおかしいことがある
boost::property_tree::write_json() の第3引数は bool で、false を渡すと整形せずに出力してくれるのだけど、なんか出力がおかしいことがある。
#include <sstream> #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/json_parser.hpp> int main(int argc, const char *argv[]) { std::stringstream s("{\"foo\": [10]}"); boost::property_tree::ptree pt; boost::property_tree::read_json(s, pt); boost::property_tree::write_json(std::cout, pt, false); }
{"foo":["10" ]}
おいなんだそのスペースは。
と言うかこれは Property Tree の構造とは関係なさそうだし普通にバグかもしれない。
と言うわけでまとめると、Property Tree は JSON ライブラリではありません!本当にちゃんと JSON を扱いたい場合は専用の JSON ライブラリを使いましょう。