id,summary,reporter,owner,description,type,status,milestone,component,version,severity,resolution,keywords,cc 3828,No way to create smaller json output from property_tree::write_json,Michael Anderson ,Sebastian Redl,"The current implementation of write_json is filled with whitespace and newlines. This makes it very nice for human readability, but not so nice for sending over the network. It would be nice to have a way to write compact JSON. I've implemented stripped down versions of the JSON writer that does this, however there is a heap of common code between this version and the non-compact version that could/should be factored out. Heres a sample program {{{ #include ""boost/property_tree/json_parser.hpp"" #include ""boost/array.hpp"" boost::property_tree::ptree foo() { boost::property_tree::ptree retval; retval.put(""moo"",""12345""); retval.put(""zoo"",12345); return retval; } boost::property_tree::ptree bar() { boost::property_tree::ptree retval; retval.put(""mork"",""hello""); return retval; } int main() { // std::stringstream ss; boost::property_tree::ptree pt; pt.put_child(""foo"", foo() ); pt.put_child(""bar"", bar() ); boost::property_tree::write_json(std::cout, pt ); boost::property_tree::write_json_compact(std::cout, pt ); } }}} The output is: {{{ ""foo"": { ""moo"": ""12345"", ""zoo"": ""12345"" }, ""bar"": { ""mork"": ""hello"" } } {""foo"":{""moo"":""12345"",""zoo"":""12345""},""bar"":{""mork"":""hello""}} }}} And here are the patches required to make it work {{{ Index: boost/property_tree/detail/json_parser_write.hpp =================================================================== --- boost/property_tree/detail/json_parser_write.hpp (revision 58794) +++ boost/property_tree/detail/json_parser_write.hpp (working copy) @@ -118,6 +117,56 @@ } + template + void write_json_helper_compact(std::basic_ostream &stream, + const Ptree &pt) + { + + typedef typename Ptree::key_type::value_type Ch; + typedef typename std::basic_string Str; + + // Value or object or array + if ( pt.empty()) + { + + // Write value + Str data = create_escapes(pt.template get_value(), stream.getloc()); + stream << Ch('""') << data << Ch('""'); + + } + else if ( pt.count(Str()) == pt.size()) + { + + // Write array + stream << Ch('['); + typename Ptree::const_iterator it = pt.begin(); + for (; it != pt.end(); ++it) + { + write_json_helper_compact(stream, it->second); + if (boost::next(it) != pt.end()) + stream << Ch(','); + } + stream << Ch(']'); + + } + else + { + + // Write object + stream << Ch('{'); + typename Ptree::const_iterator it = pt.begin(); + for (; it != pt.end(); ++it) + { + stream << Ch('""') << create_escapes(it->first, stream.getloc()) << Ch('""') << Ch(':'); + write_json_helper_compact(stream, it->second ); + if (boost::next(it) != pt.end()) + stream << Ch(','); + } + stream << Ch('}'); + } + + } + // Verify if ptree does not contain information that cannot be written to json template bool verify_json(const Ptree &pt, int depth) @@ -159,6 +208,20 @@ BOOST_PROPERTY_TREE_THROW(json_parser_error(""write error"", filename, 0)); } + // Write ptree to json stream + template + void write_json_compact_internal(std::basic_ostream &stream, + const Ptree &pt, + const std::string &filename) + { + if (!verify_json(pt, 0)) + BOOST_PROPERTY_TREE_THROW(json_parser_error(""ptree contains data that cannot be represented in JSON format"", filename, 0)); + write_json_helper_compact(stream, pt); + stream << std::endl; + if (!stream.good()) + BOOST_PROPERTY_TREE_THROW(json_parser_error(""write error"", filename, 0)); + } + } } } #endif Index: boost/property_tree/json_parser.hpp =================================================================== --- boost/property_tree/json_parser.hpp (revision 58794) +++ boost/property_tree/json_parser.hpp (working copy) @@ -121,12 +121,61 @@ write_json_internal(stream, pt, filename); } + /** + * Translates the property tree to JSON and writes it in a compact form to + * the given output stream. + * @note Any property tree key containing only unnamed subkeys will be + * rendered as JSON arrays. + * @pre @e pt cannot contain keys that have both subkeys and non-empty data. + * @throw json_parser_error In case of error translating the property tree + * to JSON or writing to the output stream. + * @param stream The stream to which to write the JSON representation of the + * property tree. + * @param pt The property tree to tranlsate to JSON and output. + */ + template + void write_json_compact(std::basic_ostream< + typename Ptree::key_type::value_type + > &stream, + const Ptree &pt) + { + write_json_compact_internal(stream, pt, std::string()); + } + + /** + * Translates the property tree to JSON and writes it in a compact style to + * the given file. + * @note Any property tree key containing only unnamed subkeys will be + * rendered as JSON arrays. + * @pre @e pt cannot contain keys that have both subkeys and non-empty data. + * @throw json_parser_error In case of error translating the property tree + * to JSON or writing to the file. + * @param filename The name of the file to which to write the JSON + * representation of the property tree. + * @param pt The property tree to translate to JSON and output. + * @param loc The locale to use when writing out to the output file. + */ + template + void write_json_compact(const std::string &filename, + const Ptree &pt, + const std::locale &loc = std::locale()) + { + std::basic_ofstream + stream(filename.c_str()); + if (!stream) + BOOST_PROPERTY_TREE_THROW(json_parser_error( + ""cannot open file"", filename, 0)); + stream.imbue(loc); + write_json_compact_internal(stream, pt, filename); + } + } } } namespace boost { namespace property_tree { using json_parser::read_json; using json_parser::write_json; + using json_parser::write_json_compact; using json_parser::json_parser_error; } } }}} ",Bugs,closed,Boost 1.42.0,property_tree,Boost Development Trunk,Problem,fixed,,