diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp index f88278f8e..0ce16097a 100644 --- a/include/nlohmann/detail/output/serializer.hpp +++ b/include/nlohmann/detail/output/serializer.hpp @@ -110,7 +110,10 @@ class serializer const unsigned int indent_step, const unsigned int current_indent = 0) { - auto predicate = [pretty_print](const BasicJsonType&, int) { return pretty_print; }; + auto predicate = [pretty_print](const BasicJsonType&, int) + { + return pretty_print; + }; dump_configured(val, ensure_ascii, indent_step, current_indent, predicate); } @@ -132,7 +135,7 @@ class serializer byte array @param[in] val value to serialize - @param[in] pretty_print whether the output shall be pretty-printed based + @param[in] pretty_print whether the output shall be pretty-printed based on the value and current identation @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters in the output are escaped with `\uXXXX` sequences, and the result consists @@ -142,10 +145,10 @@ class serializer */ template void dump_configured(const BasicJsonType& val, - const bool ensure_ascii, - const unsigned int indent_step, - const unsigned int current_indent, - const PrettyPrintPredicate& pretty_print) + const bool ensure_ascii, + const unsigned int indent_step, + const unsigned int current_indent, + const PrettyPrintPredicate& pretty_print) { switch (val.m_type) { @@ -243,8 +246,8 @@ class serializer // first n-1 elements for (auto i = val.m_value.array->cbegin(); - i != val.m_value.array->cend() - 1; - ++i) + i != val.m_value.array->cend() - 1; + ++i) { o->write_characters(indent_string.c_str(), new_indent); dump_configured(*i, ensure_ascii, indent_step, new_indent, pretty_print); diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 81a443991..9a126d406 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -1267,7 +1267,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool ensure_ascii = false, const error_handler_t error_handler = error_handler_t::strict) const { - return dump(indent, indent_char, ensure_ascii, error_handler, [](basic_json const&, int) {return true;}); + return dump(indent, indent_char, ensure_ascii, error_handler, [](basic_json const&, int) + { + return true; + }); } /// @name object inspection diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index e11f52968..9af5d214c 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -18031,6 +18031,46 @@ class serializer const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent = 0) + { + auto predicate = [pretty_print](const BasicJsonType&, int) + { + return pretty_print; + }; + dump_configured(val, ensure_ascii, indent_step, current_indent, predicate); + } + + /*! + @brief internal implementation of the serialization function + + This function is called by the public member function dump and organizes + the serialization internally. The indentation level is propagated as + additional parameter. In case of arrays and objects, the function is + called recursively. If uses a predicate to decide whether to avoid pretty + printing a subtree. If the predicate returns false, pretty printing is + avoided for the whole tree, otherwise the current value is pretty printed + and the function is reevaluated for nested values. + + - strings and object keys are escaped using `escape_string()` + - integer numbers are converted implicitly via `operator<<` + - floating-point numbers are converted to a string using `"%g"` format + - binary values are serialized as objects containing the subtype and the + byte array + + @param[in] val value to serialize + @param[in] pretty_print whether the output shall be pretty-printed based + on the value and current identation + @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters + in the output are escaped with `\uXXXX` sequences, and the result consists + of ASCII characters only. + @param[in] indent_step the indent level + @param[in] current_indent the current indent level (only used internally) + */ + template + void dump_configured(const BasicJsonType& val, + const bool ensure_ascii, + const unsigned int indent_step, + const unsigned int current_indent, + const PrettyPrintPredicate& pretty_print) { switch (val.m_type) { @@ -18042,7 +18082,7 @@ class serializer return; } - if (pretty_print) + if (pretty_print(val, current_indent)) { o->write_characters("{\n", 2); @@ -18061,7 +18101,7 @@ class serializer o->write_character('\"'); dump_escaped(i->first, ensure_ascii); o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); + dump_configured(i->second, ensure_ascii, indent_step, new_indent, pretty_print); o->write_characters(",\n", 2); } @@ -18072,7 +18112,7 @@ class serializer o->write_character('\"'); dump_escaped(i->first, ensure_ascii); o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); + dump_configured(i->second, ensure_ascii, indent_step, new_indent, pretty_print); o->write_character('\n'); o->write_characters(indent_string.c_str(), current_indent); @@ -18115,7 +18155,7 @@ class serializer return; } - if (pretty_print) + if (pretty_print(val, current_indent)) { o->write_characters("[\n", 2); @@ -18128,17 +18168,18 @@ class serializer // first n-1 elements for (auto i = val.m_value.array->cbegin(); - i != val.m_value.array->cend() - 1; ++i) + 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_configured(*i, ensure_ascii, indent_step, new_indent, pretty_print); o->write_characters(",\n", 2); } // last element JSON_ASSERT(!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_configured(val.m_value.array->back(), ensure_ascii, indent_step, new_indent, pretty_print); o->write_character('\n'); o->write_characters(indent_string.c_str(), current_indent); @@ -18176,7 +18217,7 @@ class serializer case value_t::binary: { - if (pretty_print) + if (pretty_print(val, current_indent)) { o->write_characters("{\n", 2); @@ -20482,13 +20523,32 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const char indent_char = ' ', const bool ensure_ascii = false, const error_handler_t error_handler = error_handler_t::strict) const + { + return dump(indent, indent_char, ensure_ascii, error_handler, [](basic_json const&, int) + { + return true; + }); + } + + /// @name object inspection + /// Functions to inspect the type of a JSON value. + /// @{ + + /// @brief serialization + /// @sa https://json.nlohmann.me/api/basic_json/dump/ + template + string_t dump(const int indent, + const char indent_char, + const bool ensure_ascii, + const error_handler_t error_handler, + const PrettyPrintPredicate& pretty_print) const { string_t result; serializer s(detail::output_adapter(result), indent_char, error_handler); if (indent >= 0) { - s.dump(*this, true, ensure_ascii, static_cast(indent)); + s.dump_configured(*this, ensure_ascii, static_cast(indent), 0, pretty_print); } else { diff --git a/tests/src/unit-serialization.cpp b/tests/src/unit-serialization.cpp index dc54d73b6..05914fd34 100644 --- a/tests/src/unit-serialization.cpp +++ b/tests/src/unit-serialization.cpp @@ -81,9 +81,12 @@ TEST_CASE("serialization") { SECTION("no pretty primitive arrays") { - auto pretty_print = [](json const& x, int) + auto pretty_print = [](json const & x, int) { - return !x.is_array() || std::any_of(x.cbegin(), x.cend(), [](json const& e) { return !e.is_primitive(); }); + return !x.is_array() || std::any_of(x.cbegin(), x.cend(), [](json const & e) + { + return !e.is_primitive(); + }); }; const json j = {{"foo", {1, 2, 3}}};