Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Boost property tree write_json save everything as string? Is it possible to change that?

I'm trying to serialize using boost property tree write_json, it saves everything as strings, it's not that data are wrong, but I need to cast them explicitly every time and I want to use them somewhere else. (like in python or other C++ json (non boost) library)

here is some sample code and what I get depending on locale:

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. like this:

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

Is there anyway to save them as the values, like: "key1" : true or "key2" : 2.2?

like image 826
pprzemek Avatar asked May 18 '10 08:05

pprzemek


1 Answers

Ok, I've solved it like this, (of course it won't suite for everybody, as it is a bit of a hack, that need further work).


I've wrote my own write_json function (simply copied the files, json_parser.hpp and json_parser_write.hpp to my project) and modified the following lines in json_parser_write.hpp:

  1. commented line 37 - escaping the quote '"'
  2. changed line 76 - so that it doesn't add quotes anymore: stream << Ch('"') << data << Ch('"'); ==> stream << data;

Then values will be saved properly except for strings, so I wrote custom 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 simply saved string using:

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

complete 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"             }         ]     } } 
like image 174
pprzemek Avatar answered Sep 23 '22 03:09

pprzemek