#3828 closed Bugs (fixed)
No way to create smaller json output from property_tree::write_json
Reported by: | Owned by: | Sebastian Redl | |
---|---|---|---|
Milestone: | Boost 1.42.0 | Component: | property_tree |
Version: | Boost Development Trunk | Severity: | Problem |
Keywords: | Cc: |
Description
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<class Ptree> + void write_json_helper_compact(std::basic_ostream<typename Ptree::key_type::value_type> &stream, + const Ptree &pt) + { + + typedef typename Ptree::key_type::value_type Ch; + typedef typename std::basic_string<Ch> Str; + + // Value or object or array + if ( pt.empty()) + { + + // Write value + Str data = create_escapes(pt.template get_value<Str>(), 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<class Ptree> 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<class Ptree> + void write_json_compact_internal(std::basic_ostream<typename Ptree::key_type::value_type> &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<class Ptree> + 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<class Ptree> + void write_json_compact(const std::string &filename, + const Ptree &pt, + const std::locale &loc = std::locale()) + { + std::basic_ofstream<typename Ptree::key_type::value_type> + 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; } }
Change History (5)
comment:1 by , 13 years ago
comment:2 by , 13 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
(In [59739]) Give the JSON writer the ability to NOT pretty-print, but instead produce compact code. Fixes bug 3828. But I still have to write test cases for the JSON writer; there aren't ANY!
follow-up: 4 comment:3 by , 10 years ago
dear boost, in 1.50 release, compact JSON *almost* works correctly, there's still an additional newline that's harmful, just like the previous comment says.
Oops there's an additional
stream << std::endl;
that should be removed from the patch.
comment:4 by , 8 years ago
Replying to anonymous:
dear boost, in 1.50 release, compact JSON *almost* works correctly, there's still an additional newline that's harmful, just like the previous comment says.
Oops there's an additional
stream << std::endl;
that should be removed from the patch.
Issue is still present in boost 1.57.
Oops there's an additional
that should be removed from the patch.