Why does the Boost write_json property tree save everything as a string? Can this be changed?

I am trying to serialize using the boost_json property tree, it saves everything as strings, it is not that the data is erroneous, but I need to specify them every time, and I want to use them somewhere else. (e.g. in python or another C ++ json library (non boost))

here is a sample code and what i get depending on the language:

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(); 

and my_string_to_send_somewhere_else is sth. eg:

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

Is there a way to save them as values, for example: "key1" : true or "key2" : 2.2 ?

+56
json boost boost-propertytree
May 18 '10 at 8:52 a.m.
source share
5 answers

Well, I decided it this way (of course, this will not be for everyone, since it is a little hack, which requires further work).




I wrote my own write_json function (just copied the files json_parser.hpp and json_parser_write.hpp into my project) and changed the following lines in json_parser_write.hpp :

  • comment line 37 - escape quotation '' '
  • line 76 has been changed so that it no longer adds quotation marks: stream << Ch('"') << data << Ch('"'); ==> stream << data; stream << Ch('"') << data << Ch('"'); ==> stream << data;



Then the values ​​will be saved correctly, except for the lines, so I wrote my own translator for it:

 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 +'"'; } }; 

and just save the line using:

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

full program:

 #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; } 

result:)

 { "path1": { "path2": [ { "int": 10, "bool": true }, { "double": 2.2, "string": "some string" } ] } } 
+33
May 18 '10 at 20:52
source share

Boost confirms that its implementation does not have 100% JSON compliance. Check out the following link: Creating a ptree variant that stores JSON types is a future plan, but far away. !

+10
Nov 05 '14 at 2:38
source share

The simplest and cleanest solution I could come up with is to create JSON with placeholders and at the end of the line, replacing the actual value, highlighting extra quotes.

 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); } 

And the result

{"Command": "getOrders", "arguments": {"pendingOnly": true "someIntValue": 15}}

+5
Feb 28 '15 at 11:29
source share

As we have typedef basic_ptree <std :: string, std :: string> Ptree; in alarm libraries boost will always serialize each value as a string and parse all values ​​with the equivalent string.

+3
Mar 10 '14 at 11:23
source share

From the outputted JSON, it is clear that the serializer serializes all strings using some kind of .toString () method, that is, it does not know about the type of each member and therefore contains everything.

For more on this issue, see Creating JSON Arrays in Boost Using Property Trees .

+2
May 18 '10 at 13:22
source share



All Articles