implemented pretty printing (issue #13)

- to_string() method is now called dump()
- syntax borrowed from Python’s json.dumps()
This commit is contained in:
Niels 2015-01-06 21:44:07 +01:00
parent 08456b8ff0
commit bd9f49efb9
4 changed files with 126 additions and 28 deletions

View file

@ -472,8 +472,22 @@ json::operator object_t() const
return get<object_t>();
}
const std::string json::to_string() const noexcept
/*!
Internal implementation of the serialization function.
\param prettyPrint whether the output shall be pretty-printed
\param indentStep the indent level
\param currentIndent the current indent level (only used internally)
*/
const std::string json::dump(const bool prettyPrint,
const unsigned int indentStep, unsigned int currentIndent) const noexcept
{
// helper function to return whitespace as indentation
const auto indent = [prettyPrint, &currentIndent]()
{
return prettyPrint ? std::string(currentIndent, ' ') : std::string();
};
switch (type_)
{
case (value_type::string):
@ -498,34 +512,73 @@ const std::string json::to_string() const noexcept
case (value_type::array):
{
std::string result;
if (value_.array->empty())
{
return "[]";
}
std::string result = "[";
// increase indentation
if (prettyPrint)
{
currentIndent += indentStep;
result += "\n";
}
for (array_t::const_iterator i = value_.array->begin(); i != value_.array->end(); ++i)
{
if (i != value_.array->begin())
{
result += ", ";
result += prettyPrint ? ",\n" : ", ";
}
result += i->to_string();
result += indent() + i->dump(prettyPrint, indentStep, currentIndent);
}
return "[" + result + "]";
// decrease indentation
if (prettyPrint)
{
currentIndent -= indentStep;
result += "\n";
}
return result + indent() + "]";
}
case (value_type::object):
{
std::string result;
if (value_.object->empty())
{
return "{}";
}
std::string result = "{";
// increase indentation
if (prettyPrint)
{
currentIndent += indentStep;
result += "\n";
}
for (object_t::const_iterator i = value_.object->begin(); i != value_.object->end(); ++i)
{
if (i != value_.object->begin())
{
result += ", ";
result += prettyPrint ? ",\n" : ", ";
}
result += "\"" + i->first + "\": " + i->second.to_string();
result += indent() + "\"" + i->first + "\": " + i->second.dump(prettyPrint, indentStep,
currentIndent);
}
return "{" + result + "}";
// decrease indentation
if (prettyPrint)
{
currentIndent -= indentStep;
result += "\n";
}
return result + indent() + "}";
}
// actually only value_type::null - but making the compiler happy
@ -536,6 +589,29 @@ const std::string json::to_string() const noexcept
}
}
/*!
Serialization function for JSON objects. The function tries to mimick Python's
\p json.dumps() function, and currently supports its \p indent parameter.
\param indent if indent is nonnegative, then array elements and object members
will be pretty-printed with that indent level. An indent level
of 0 will only insert newlines. -1 (the default) selects the
most compact representation
\see https://docs.python.org/2/library/json.html#json.dump
*/
const std::string json::dump(int indent) const noexcept
{
if (indent >= 0)
{
return dump(true, static_cast<unsigned int>(indent));
}
else
{
return dump(false, 0);
}
}
///////////////////////////////////////////
// ADDING ELEMENTS TO OBJECTS AND ARRAYS //

View file

@ -162,6 +162,9 @@ class json
/// return the type as string
const std::string type_name() const noexcept;
/// dump the object (with pretty printer)
const std::string dump(const bool, const unsigned int, unsigned int = 0) const noexcept;
public:
/// explicit value conversion
template<typename T>
@ -180,34 +183,34 @@ class json
/// implicit conversion to JSON map (only for objects)
operator object_t() const;
/// write to stream
/// serialize to stream
friend std::ostream& operator<<(std::ostream& o, const json& j)
{
o << j.to_string();
o << j.dump();
return o;
}
/// write to stream
/// serialize to stream
friend std::ostream& operator>>(const json& j, std::ostream& o)
{
o << j.to_string();
o << j.dump();
return o;
}
/// read from stream
/// deserialize from stream
friend std::istream& operator>>(std::istream& i, json& j)
{
j = parser(i).parse();
return i;
}
/// read from stream
/// deserialize from stream
friend std::istream& operator<<(json& j, std::istream& i)
{
j = parser(i).parse();
return i;
}
/// explicit conversion to string representation (C++ style)
const std::string to_string() const noexcept;
/// explicit serialization
const std::string dump(int = -1) const noexcept;
/// add an object/array to an array
json& operator+=(const json&);