From 186c7df25ae37a279b59d68356c1b8c56220bb70 Mon Sep 17 00:00:00 2001 From: Evan Driscoll Date: Sat, 2 Jun 2018 23:10:28 -0500 Subject: [PATCH] Can style subobjects of a object differently, by key --- .../detail/output/fancy_serializer.hpp | 45 ++++++++++++++---- include/nlohmann/json.hpp | 2 + single_include/nlohmann/json.hpp | 47 +++++++++++++++---- test/src/unit-fancy-serialization.cpp | 38 +++++++++++++++ 4 files changed, 116 insertions(+), 16 deletions(-) diff --git a/include/nlohmann/detail/output/fancy_serializer.hpp b/include/nlohmann/detail/output/fancy_serializer.hpp index 87fd9578e..2d783b77c 100644 --- a/include/nlohmann/detail/output/fancy_serializer.hpp +++ b/include/nlohmann/detail/output/fancy_serializer.hpp @@ -36,14 +36,16 @@ struct fancy_serializer_style }; template -class fancy_serializer_stylizer +class basic_fancy_serializer_stylizer { public: - fancy_serializer_stylizer(fancy_serializer_style const& ds) + using string_t = typename BasicJsonType::string_t; + + basic_fancy_serializer_stylizer(fancy_serializer_style const& ds) : default_style(ds) {} - fancy_serializer_stylizer() = delete; + basic_fancy_serializer_stylizer() = default; public: const fancy_serializer_style& get_default_style() const @@ -51,8 +53,26 @@ class fancy_serializer_stylizer return default_style; } + fancy_serializer_style& get_default_style() + { + return default_style; + } + + const fancy_serializer_style& get_style(const string_t& j) const + { + auto iter = key_styles.find(j); + return iter == key_styles.end() ? default_style : iter->second; + } + + fancy_serializer_style& get_or_insert_style(const string_t& j) + { + return key_styles[j]; + } + private: fancy_serializer_style default_style; + + std::map key_styles; }; namespace detail @@ -64,7 +84,7 @@ namespace detail template class fancy_serializer { - using stylizer_t = fancy_serializer_stylizer; + using stylizer_t = basic_fancy_serializer_stylizer; using primitive_serializer_t = primitive_serializer; using string_t = typename BasicJsonType::string_t; using number_float_t = typename BasicJsonType::number_float_t; @@ -216,7 +236,8 @@ class fancy_serializer o->write_character('\"'); prim_serializer.dump_escaped(*o, i->first, ensure_ascii); o->write_characters("\": ", 2 + newline_len); - dump(i->second, ensure_ascii, depth + 1, active_style); + auto new_style = &stylizer.get_style(i->first); + dump(i->second, ensure_ascii, depth + 1, new_style); o->write_characters(",\n", 1 + newline_len); } @@ -227,7 +248,8 @@ class fancy_serializer o->write_character('\"'); prim_serializer.dump_escaped(*o, i->first, ensure_ascii); o->write_characters("\": ", 2 + newline_len); - dump(i->second, ensure_ascii, depth + 1, active_style); + auto new_style = &stylizer.get_style(i->first); + dump(i->second, ensure_ascii, depth + 1, new_style); o->write_characters("\n", newline_len); o->write_characters(indent_string.c_str(), old_indent); @@ -360,13 +382,20 @@ class fancy_serializer template std::ostream& fancy_dump(std::ostream& o, const BasicJsonType& j, - fancy_serializer_style style) + basic_fancy_serializer_stylizer const& stylizer) { - fancy_serializer_stylizer stylizer(style); // do the actual serialization detail::fancy_serializer s(detail::output_adapter(o), stylizer); s.dump(j, false); return o; } +template +std::ostream& fancy_dump(std::ostream& o, const BasicJsonType& j, + fancy_serializer_style style) +{ + basic_fancy_serializer_stylizer stylizer(style); + return fancy_dump(o, j, stylizer); +} + } diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index b2836b6ca..16984d5f7 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -7624,6 +7624,8 @@ class basic_json /// @} }; + +using fancy_serializer_stylizer = basic_fancy_serializer_stylizer; } // namespace nlohmann /////////////////////// diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index e05568136..0009c3715 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -10106,14 +10106,16 @@ struct fancy_serializer_style }; template -class fancy_serializer_stylizer +class basic_fancy_serializer_stylizer { public: - fancy_serializer_stylizer(fancy_serializer_style const& ds) + using string_t = typename BasicJsonType::string_t; + + basic_fancy_serializer_stylizer(fancy_serializer_style const& ds) : default_style(ds) {} - fancy_serializer_stylizer() = delete; + basic_fancy_serializer_stylizer() = default; public: const fancy_serializer_style& get_default_style() const @@ -10121,8 +10123,26 @@ class fancy_serializer_stylizer return default_style; } + fancy_serializer_style& get_default_style() + { + return default_style; + } + + const fancy_serializer_style& get_style(const string_t& j) const + { + auto iter = key_styles.find(j); + return iter == key_styles.end() ? default_style : iter->second; + } + + fancy_serializer_style& get_or_insert_style(const string_t& j) + { + return key_styles[j]; + } + private: fancy_serializer_style default_style; + + std::map key_styles; }; namespace detail @@ -10134,7 +10154,7 @@ namespace detail template class fancy_serializer { - using stylizer_t = fancy_serializer_stylizer; + using stylizer_t = basic_fancy_serializer_stylizer; using primitive_serializer_t = primitive_serializer; using string_t = typename BasicJsonType::string_t; using number_float_t = typename BasicJsonType::number_float_t; @@ -10286,7 +10306,8 @@ class fancy_serializer o->write_character('\"'); prim_serializer.dump_escaped(*o, i->first, ensure_ascii); o->write_characters("\": ", 2 + newline_len); - dump(i->second, ensure_ascii, depth + 1, active_style); + auto new_style = &stylizer.get_style(i->first); + dump(i->second, ensure_ascii, depth + 1, new_style); o->write_characters(",\n", 1 + newline_len); } @@ -10297,7 +10318,8 @@ class fancy_serializer o->write_character('\"'); prim_serializer.dump_escaped(*o, i->first, ensure_ascii); o->write_characters("\": ", 2 + newline_len); - dump(i->second, ensure_ascii, depth + 1, active_style); + auto new_style = &stylizer.get_style(i->first); + dump(i->second, ensure_ascii, depth + 1, new_style); o->write_characters("\n", newline_len); o->write_characters(indent_string.c_str(), old_indent); @@ -10430,15 +10452,22 @@ class fancy_serializer template std::ostream& fancy_dump(std::ostream& o, const BasicJsonType& j, - fancy_serializer_style style) + basic_fancy_serializer_stylizer const& stylizer) { - fancy_serializer_stylizer stylizer(style); // do the actual serialization detail::fancy_serializer s(detail::output_adapter(o), stylizer); s.dump(j, false); return o; } +template +std::ostream& fancy_dump(std::ostream& o, const BasicJsonType& j, + fancy_serializer_style style) +{ + basic_fancy_serializer_stylizer stylizer(style); + return fancy_dump(o, j, stylizer); +} + } // #include @@ -18811,6 +18840,8 @@ class basic_json /// @} }; + +using fancy_serializer_stylizer = basic_fancy_serializer_stylizer; } // namespace nlohmann /////////////////////// diff --git a/test/src/unit-fancy-serialization.cpp b/test/src/unit-fancy-serialization.cpp index c50a1365f..8c82a32c4 100644 --- a/test/src/unit-fancy-serialization.cpp +++ b/test/src/unit-fancy-serialization.cpp @@ -34,6 +34,7 @@ SOFTWARE. using nlohmann::json; using nlohmann::fancy_dump; using nlohmann::fancy_serializer_style; +using nlohmann::fancy_serializer_stylizer; // Chops off the first line (if empty, but if it *isn't* empty you're // probably using this wrong), measures the leading indent on the @@ -77,6 +78,13 @@ std::string fancy_to_string(json j, fancy_serializer_style style = fancy_seriali return ss.str(); } +std::string fancy_to_string(json j, fancy_serializer_stylizer stylizer) +{ + std::stringstream ss; + fancy_dump(ss, j, stylizer); + return ss.str(); +} + TEST_CASE("serialization") { SECTION("primitives") @@ -220,6 +228,36 @@ TEST_CASE("serialization") } } + SECTION("changing styles") + { + SECTION("can style objects of a key differently") + { + fancy_serializer_stylizer stylizer; + stylizer.get_default_style().indent_step = 4; + stylizer.get_or_insert_style("one line").indent_step = 0; + + auto str = fancy_to_string( + { + { + "one line", {1, 2} + }, + { + "two lines", {1, 2} + } + }, + stylizer); + + CHECK(str == dedent(R"( + { + "one line": [1,2], + "two lines": [ + 1, + 2 + ] + })")); + } + } + SECTION("given width") { fancy_serializer_style style;