#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.