为什么提高属性树write_json保存一切为string? 有没有可能改变这一点?

我试图序列化使用boost属性树write_json,它将所有的东西保存为string,这不是数据是错误的,但我需要每次明确地投下他们,我想在别的地方使用它们。 (就像在Python或其他C ++ json(非boost)库)

这里是一些示例代码和我得到的取决于区域设置:

boost::property_tree::ptree root, arr, elem1, elem2; elem1.put<int>("key0", 0); elem1.put<bool>("key1", true); elem2.put<float>("key2", 2.2f); elem2.put<double>("key3", 3.3); arr.push_back( std::make_pair("", elem1) ); arr.push_back( std::make_pair("", elem2) ); root.put_child("path1.path2", arr); std::stringstream ss; write_json(ss, root); std::string my_string_to_send_somewhare_else = ss.str(); 

my_string_to_send_somewhere_else是。 喜欢这个:

 { "path1" : { "path2" : [ { "key0" : "0", "key1" : "true" }, { "key2" : "2.2", "key3" : "3.3" } ] } } 

有没有把它们保存为值,如: "key1" : true"key2" : 2.2

好吧,我已经解决了这个问题(当然,这不会适合所有人,因为这有点麻烦,需要进一步的工作)。


我写了自己的write_json函数(只需将文件json_parser.hppjson_parser_write.hpp复制到我的项目中),然后在json_parser_write.hpp修改以下几行:

  1. 评论第37行 – 逃避报价“”“
  2. 改变了第76行 – 以便它不再加引号: stream << Ch('"') << data << Ch('"'); ==> stream << data; stream << Ch('"') << data << Ch('"'); ==> stream << data;

然后值将被正确保存,除了string,所以我写了它的自定义翻译:

 template <typename T> struct my_id_translator { typedef T internal_type; typedef T external_type; boost::optional<T> get_value(const T &v) { return v.substr(1, v.size() - 2) ; } boost::optional<T> put_value(const T &v) { return '"' + v +'"'; } }; 

并简单地保存string使用:

 elem2.put<std::string>("key2", "asdf", my_id_translator<std::string>()); 

完整的程序:

 #include <iostream> #include <string> #include <sstream> #include <boost/property_tree/ptree.hpp> #include "property_tree/json_parser.hpp" // copied the headers template <typename T> struct my_id_translator { typedef T internal_type; typedef T external_type; boost::optional<T> get_value(const T &v) { return v.substr(1, v.size() - 2) ; } boost::optional<T> put_value(const T &v) { return '"' + v +'"'; } }; int main(int, char *[]) { using namespace std; using boost::property_tree::ptree; using boost::property_tree::basic_ptree; try { ptree root, arr,elem2; basic_ptree<std::string, std::string> elem1; elem1.put<int>("int", 10 ); elem1.put<bool>("bool", true); elem2.put<double>("double", 2.2); elem2.put<std::string>("string", "some string", my_id_translator<std::string>()); arr.push_back( std::make_pair("", elem1) ); arr.push_back( std::make_pair("", elem2) ); root.put_child("path1.path2", arr); std::stringstream ss; write_json(ss, root); std::string my_string_to_send_somewhere_else = ss.str(); cout << my_string_to_send_somewhere_else << endl; } catch (std::exception & e) { cout << e.what(); } return 0; } 

结果:)

 { "path1": { "path2": [ { "int": 10, "bool": true }, { "double": 2.2, "string": "some string" } ] } } 

Boost确认其实现没有100%符合JSON标准。 检查下面的链接,看看他们的解释: 做一个保留JSONtypes的ptree变体是未来的计划,但远非如此。 !

因为我们有typedef basic_ptree <std :: string,std :: string> ptree; 在boost库中,boost将始终将每个值串行化为string,并将所有值parsing为string等效项。

我可以想出最简单,最干净的解决scheme是用占位符生成JSON,并在最后一个string中replace实际的值,并将多余的引号分开。

 static string buildGetOrdersCommand() { ptree root; ptree element; element.put<string>("pendingOnly", ":pendingOnly"); element.put<string>("someIntValue", ":someIntValue"); root.put("command", "getOrders"); root.put_child("arguments", element); std::ostringstream buf; write_json(buf, root, false); buf << std::endl; string json = buf.str(); replace(json, ":pendingOnly", "true"); replace(json, ":someIntValue", std::to_string(15)); return json; } static void replace(string& json, const string& placeholder, const string& value) { boost::replace_all<string>(json, "\"" + placeholder + "\"", value); } 

结果是

{ “命令”: “getOrders”, “参数”:{ “pendingOnly”:真 “someIntValue”:15}}

从输出的JSON中可以明显看出,序列化程序使用某种.toString()方法将所有内容序列化为string – 也就是说,它不知道每个成员的types,因此将所有内容都包含在“”中。

有关此问题的更多信息,请参阅使用属性树在Boost中创buildJSON数组 。