[Boost-bugs] [Boost C++ Libraries] #3828: No way to create smaller json output from property_tree::write_json

Subject: [Boost-bugs] [Boost C++ Libraries] #3828: No way to create smaller json output from property_tree::write_json
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2010-01-08 01:16:59


#3828: No way to create smaller json output from property_tree::write_json
-----------------------------------------------------+----------------------
 Reporter: Michael Anderson <drmikeando@…> | Owner: cornedbee
     Type: Bugs | Status: new
Milestone: Boost 1.42.0 | Component: property_tree
  Version: Boost Development Trunk | Severity: Problem
 Keywords: |
-----------------------------------------------------+----------------------
 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;
  } }

 }}}

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/3828>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:02 UTC