diff --git a/include/nlohmann/detail/output/fancy_serializer.hpp b/include/nlohmann/detail/output/fancy_serializer.hpp index ad785f079..c3fba10fd 100644 --- a/include/nlohmann/detail/output/fancy_serializer.hpp +++ b/include/nlohmann/detail/output/fancy_serializer.hpp @@ -23,6 +23,13 @@ namespace nlohmann { + +struct fancy_serializer_style +{ + unsigned int indent_step = 0; + char indent_char = ' '; +}; + namespace detail { /////////////////// @@ -45,8 +52,9 @@ class fancy_serializer @param[in] s output stream to serialize to @param[in] ichar indentation character to use */ - fancy_serializer(output_adapter_t s, const char ichar) - : o(std::move(s)), indent_char(ichar), indent_string(512, indent_char) + fancy_serializer(output_adapter_t s, + const fancy_serializer_style& st) + : o(std::move(s)), indent_string(512, st.indent_char), style(st) {} // delete because of pointer members @@ -70,9 +78,8 @@ class fancy_serializer @param[in] indent_step the indent level @param[in] current_indent the current indent level (only used internally) */ - void dump(const BasicJsonType& val, const bool pretty_print, + void dump(const BasicJsonType& val, const bool ensure_ascii, - const unsigned int indent_step, const unsigned int current_indent = 0) { switch (val.m_type) @@ -85,12 +92,12 @@ class fancy_serializer return; } - if (pretty_print) + if (style.indent_step > 0) { o->write_characters("{\n", 2); // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; + const auto new_indent = current_indent + style.indent_step; if (JSON_UNLIKELY(indent_string.size() < new_indent)) { indent_string.resize(indent_string.size() * 2, ' '); @@ -104,7 +111,7 @@ class fancy_serializer o->write_character('\"'); prim_serializer.dump_escaped(*o, i->first, ensure_ascii); o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); + dump(i->second, ensure_ascii, new_indent); o->write_characters(",\n", 2); } @@ -115,7 +122,7 @@ class fancy_serializer o->write_character('\"'); prim_serializer.dump_escaped(*o, i->first, ensure_ascii); o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); + dump(i->second, ensure_ascii, new_indent); o->write_character('\n'); o->write_characters(indent_string.c_str(), current_indent); @@ -132,7 +139,7 @@ class fancy_serializer o->write_character('\"'); prim_serializer.dump_escaped(*o, i->first, ensure_ascii); o->write_characters("\":", 2); - dump(i->second, false, ensure_ascii, indent_step, current_indent); + dump(i->second, ensure_ascii, current_indent); o->write_character(','); } @@ -142,7 +149,7 @@ class fancy_serializer o->write_character('\"'); prim_serializer.dump_escaped(*o, i->first, ensure_ascii); o->write_characters("\":", 2); - dump(i->second, false, ensure_ascii, indent_step, current_indent); + dump(i->second, ensure_ascii, current_indent); o->write_character('}'); } @@ -158,12 +165,12 @@ class fancy_serializer return; } - if (pretty_print) + if (style.indent_step > 0) { o->write_characters("[\n", 2); // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; + const auto new_indent = current_indent + style.indent_step; if (JSON_UNLIKELY(indent_string.size() < new_indent)) { indent_string.resize(indent_string.size() * 2, ' '); @@ -174,14 +181,14 @@ class fancy_serializer i != val.m_value.array->cend() - 1; ++i) { o->write_characters(indent_string.c_str(), new_indent); - dump(*i, true, ensure_ascii, indent_step, new_indent); + dump(*i, ensure_ascii, new_indent); o->write_characters(",\n", 2); } // last element assert(not val.m_value.array->empty()); o->write_characters(indent_string.c_str(), new_indent); - dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); + dump(val.m_value.array->back(), ensure_ascii, new_indent); o->write_character('\n'); o->write_characters(indent_string.c_str(), current_indent); @@ -195,13 +202,13 @@ class fancy_serializer for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i) { - dump(*i, false, ensure_ascii, indent_step, current_indent); + dump(*i, ensure_ascii, current_indent); o->write_character(','); } // last element assert(not val.m_value.array->empty()); - dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); + dump(val.m_value.array->back(), ensure_ascii, current_indent); o->write_character(']'); } @@ -266,24 +273,25 @@ class fancy_serializer /// the output of the fancy_serializer output_adapter_t o = nullptr; - /// the indentation character - const char indent_char; /// the indentation string string_t indent_string; /// Used for serializing "base" objects. Strings are sort of /// counted in this, but not completely. primitive_serializer_t prim_serializer; + + /// Output style + fancy_serializer_style style; }; } template std::ostream& fancy_dump(std::ostream& o, const BasicJsonType& j, - unsigned int indent_step, char indent_char) + fancy_serializer_style style) { // do the actual serialization - detail::fancy_serializer s(detail::output_adapter(o), indent_char); - s.dump(j, indent_step > 0, false, indent_step); + detail::fancy_serializer s(detail::output_adapter(o), style); + s.dump(j, false, 0u); return o; } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 0a9ada08c..c6fc6a283 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -10093,6 +10093,13 @@ class serializer namespace nlohmann { + +struct fancy_serializer_style +{ + unsigned int indent_step = 0; + char indent_char = ' '; +}; + namespace detail { /////////////////// @@ -10115,8 +10122,9 @@ class fancy_serializer @param[in] s output stream to serialize to @param[in] ichar indentation character to use */ - fancy_serializer(output_adapter_t s, const char ichar) - : o(std::move(s)), indent_char(ichar), indent_string(512, indent_char) + fancy_serializer(output_adapter_t s, + const fancy_serializer_style& st) + : o(std::move(s)), indent_string(512, st.indent_char), style(st) {} // delete because of pointer members @@ -10140,9 +10148,8 @@ class fancy_serializer @param[in] indent_step the indent level @param[in] current_indent the current indent level (only used internally) */ - void dump(const BasicJsonType& val, const bool pretty_print, + void dump(const BasicJsonType& val, const bool ensure_ascii, - const unsigned int indent_step, const unsigned int current_indent = 0) { switch (val.m_type) @@ -10155,12 +10162,12 @@ class fancy_serializer return; } - if (pretty_print) + if (style.indent_step > 0) { o->write_characters("{\n", 2); // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; + const auto new_indent = current_indent + style.indent_step; if (JSON_UNLIKELY(indent_string.size() < new_indent)) { indent_string.resize(indent_string.size() * 2, ' '); @@ -10174,7 +10181,7 @@ class fancy_serializer o->write_character('\"'); prim_serializer.dump_escaped(*o, i->first, ensure_ascii); o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); + dump(i->second, ensure_ascii, new_indent); o->write_characters(",\n", 2); } @@ -10185,7 +10192,7 @@ class fancy_serializer o->write_character('\"'); prim_serializer.dump_escaped(*o, i->first, ensure_ascii); o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); + dump(i->second, ensure_ascii, new_indent); o->write_character('\n'); o->write_characters(indent_string.c_str(), current_indent); @@ -10202,7 +10209,7 @@ class fancy_serializer o->write_character('\"'); prim_serializer.dump_escaped(*o, i->first, ensure_ascii); o->write_characters("\":", 2); - dump(i->second, false, ensure_ascii, indent_step, current_indent); + dump(i->second, ensure_ascii, current_indent); o->write_character(','); } @@ -10212,7 +10219,7 @@ class fancy_serializer o->write_character('\"'); prim_serializer.dump_escaped(*o, i->first, ensure_ascii); o->write_characters("\":", 2); - dump(i->second, false, ensure_ascii, indent_step, current_indent); + dump(i->second, ensure_ascii, current_indent); o->write_character('}'); } @@ -10228,12 +10235,12 @@ class fancy_serializer return; } - if (pretty_print) + if (style.indent_step > 0) { o->write_characters("[\n", 2); // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; + const auto new_indent = current_indent + style.indent_step; if (JSON_UNLIKELY(indent_string.size() < new_indent)) { indent_string.resize(indent_string.size() * 2, ' '); @@ -10244,14 +10251,14 @@ class fancy_serializer i != val.m_value.array->cend() - 1; ++i) { o->write_characters(indent_string.c_str(), new_indent); - dump(*i, true, ensure_ascii, indent_step, new_indent); + dump(*i, ensure_ascii, new_indent); o->write_characters(",\n", 2); } // last element assert(not val.m_value.array->empty()); o->write_characters(indent_string.c_str(), new_indent); - dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); + dump(val.m_value.array->back(), ensure_ascii, new_indent); o->write_character('\n'); o->write_characters(indent_string.c_str(), current_indent); @@ -10265,13 +10272,13 @@ class fancy_serializer for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i) { - dump(*i, false, ensure_ascii, indent_step, current_indent); + dump(*i, ensure_ascii, current_indent); o->write_character(','); } // last element assert(not val.m_value.array->empty()); - dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); + dump(val.m_value.array->back(), ensure_ascii, current_indent); o->write_character(']'); } @@ -10336,24 +10343,25 @@ class fancy_serializer /// the output of the fancy_serializer output_adapter_t o = nullptr; - /// the indentation character - const char indent_char; /// the indentation string string_t indent_string; /// Used for serializing "base" objects. Strings are sort of /// counted in this, but not completely. primitive_serializer_t prim_serializer; + + /// Output style + fancy_serializer_style style; }; } template std::ostream& fancy_dump(std::ostream& o, const BasicJsonType& j, - unsigned int indent_step, char indent_char) + fancy_serializer_style style) { // do the actual serialization - detail::fancy_serializer s(detail::output_adapter(o), indent_char); - s.dump(j, indent_step > 0, false, indent_step); + detail::fancy_serializer s(detail::output_adapter(o), style); + s.dump(j, false, 0u); return o; } diff --git a/test/src/unit-fancy-serialization.cpp b/test/src/unit-fancy-serialization.cpp index 46c1f4cea..17eb6ba3d 100644 --- a/test/src/unit-fancy-serialization.cpp +++ b/test/src/unit-fancy-serialization.cpp @@ -33,11 +33,12 @@ SOFTWARE. using nlohmann::json; using nlohmann::fancy_dump; +using nlohmann::fancy_serializer_style; -std::string fancy_to_string(json j, unsigned int indent_step = 0, char indent_char = ' ') +std::string fancy_to_string(json j, fancy_serializer_style style = fancy_serializer_style()) { std::stringstream ss; - fancy_dump(ss, j, indent_step, indent_char); + fancy_dump(ss, j, style); return ss.str(); } @@ -78,7 +79,9 @@ TEST_CASE("serialization") SECTION("given width") { - auto str = fancy_to_string({"foo", 1, 2, 3, false, {{"one", 1}}}, 4); + fancy_serializer_style style; + style.indent_step = 4; + auto str = fancy_to_string({"foo", 1, 2, 3, false, {{"one", 1}}}, style); CHECK(str == "[\n" " \"foo\",\n" @@ -95,7 +98,11 @@ TEST_CASE("serialization") SECTION("given fill") { - auto str = fancy_to_string({"foo", 1, 2, 3, false, {{"one", 1}}}, 1, '\t'); + fancy_serializer_style style; + style.indent_step = 1; + style.indent_char = '\t'; + + auto str = fancy_to_string({"foo", 1, 2, 3, false, {{"one", 1}}}, style); CHECK(str == "[\n" "\t\"foo\",\n"