From 106aeb0f0d6c254863182365e58f71aa27d56ad8 Mon Sep 17 00:00:00 2001 From: sina-rostami Date: Sun, 21 Jan 2024 15:57:41 +0330 Subject: [PATCH] Add indentation to json dump method Closes #747 --- include/crow/json.h | 63 +++++++++++++++++++++++++++++++++++++++---- tests/unittest.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 5 deletions(-) diff --git a/include/crow/json.h b/include/crow/json.h index 2fa9a6fc1..04c448b09 100644 --- a/include/crow/json.h +++ b/include/crow/json.h @@ -1840,7 +1840,14 @@ namespace crow out.push_back('"'); } - inline void dump_internal(const wvalue& v, std::string& out) const + inline void dump_indentation_part(std::string& out, const int indent, const char separator, const int indent_level) const + { + out.push_back('\n'); + out.append(indent_level * indent, separator); + } + + + inline void dump_internal(const wvalue& v, std::string& out, const int indent, const char separator, const int indent_level = 0) const { switch (v.t_) { @@ -1934,6 +1941,12 @@ namespace crow case type::List: { out.push_back('['); + + if (indent >= 0) + { + dump_indentation_part(out, indent, separator, indent_level + 1); + } + if (v.l) { bool first = true; @@ -1942,17 +1955,34 @@ namespace crow if (!first) { out.push_back(','); + + if (indent >= 0) + { + dump_indentation_part(out, indent, separator, indent_level + 1); + } } first = false; - dump_internal(x, out); + dump_internal(x, out, indent, separator, indent_level + 1); } } + + if (indent >= 0) + { + dump_indentation_part(out, indent, separator, indent_level); + } + out.push_back(']'); } break; case type::Object: { out.push_back('{'); + + if (indent >= 0) + { + dump_indentation_part(out, indent, separator, indent_level + 1); + } + if (v.o) { bool first = true; @@ -1961,13 +1991,29 @@ namespace crow if (!first) { out.push_back(','); + if (indent >= 0) + { + dump_indentation_part(out, indent, separator, indent_level + 1); + } } first = false; dump_string(kv.first, out); out.push_back(':'); - dump_internal(kv.second, out); + + if (indent >= 0) + { + out.push_back(' '); + } + + dump_internal(kv.second, out, indent, separator, indent_level + 1); } } + + if (indent >= 0) + { + dump_indentation_part(out, indent, separator, indent_level); + } + out.push_back('}'); } break; @@ -1979,13 +2025,20 @@ namespace crow } public: - std::string dump() const + std::string dump(const int indent, const char separator = ' ') const { std::string ret; ret.reserve(estimate_length()); - dump_internal(*this, ret); + dump_internal(*this, ret, indent, separator); return ret; } + + std::string dump() const + { + static constexpr int DontIndent = -1; + + return dump(DontIndent); + } }; // Used for accessing the internals of a wvalue diff --git a/tests/unittest.cpp b/tests/unittest.cpp index 44e40573c..375097825 100644 --- a/tests/unittest.cpp +++ b/tests/unittest.cpp @@ -943,6 +943,72 @@ TEST_CASE("json_write") CHECK(R"({"scores":[1,2,3]})" == y.dump()); } // json_write +TEST_CASE("json_write_with_indent") +{ + static constexpr int IndentationLevelOne = 1; + static constexpr int IndentationLevelTwo = 2; + static constexpr int IndentationLevelFour = 4; + + json::wvalue y; + + y["scores"][0] = 1; + y["scores"][1] = "king"; + y["scores"][2][0] = "real"; + y["scores"][2][1] = false; + y["scores"][2][2] = true; + + CHECK(R"({ + "scores": [ + 1, + "king", + [ + "real", + false, + true + ] + ] +})" == y.dump(IndentationLevelOne)); + + CHECK(R"({ + "scores": [ + 1, + "king", + [ + "real", + false, + true + ] + ] +})" == y.dump(IndentationLevelTwo)); + + CHECK(R"({ + "scores": [ + 1, + "king", + [ + "real", + false, + true + ] + ] +})" == y.dump(IndentationLevelFour)); + + static constexpr char TabSeparator = '\t'; + + CHECK(R"({ + "scores": [ + 1, + "king", + [ + "real", + false, + true + ] + ] +})" == y.dump(IndentationLevelOne, TabSeparator)); +} // json_write_with_indent + + TEST_CASE("json_copy_r_to_w_to_w_to_r") { json::rvalue r = json::load(