From cafea2acc444692e7fe99292a73a7fbc0f1ec348 Mon Sep 17 00:00:00 2001 From: Klaus Aehlig Date: Mon, 25 Apr 2022 15:22:07 +0200 Subject: json utils: support indentation up to a given depth --- src/utils/cpp/json.hpp | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'src/utils/cpp/json.hpp') diff --git a/src/utils/cpp/json.hpp b/src/utils/cpp/json.hpp index ca928ac2..471b4861 100644 --- a/src/utils/cpp/json.hpp +++ b/src/utils/cpp/json.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "gsl-lite/gsl-lite.hpp" #include "nlohmann/json.hpp" @@ -70,6 +71,58 @@ namespace detail { return json.dump(); } +// NOLINTNEXTLINE(misc-no-recursion) +[[nodiscard]] static inline auto IndentOnlyUntilDepth( + nlohmann::json const& json, + std::string const& indent, + std::size_t until, + std::size_t depth, + std::optional path, + std::unordered_map const& depths) -> std::string { + using iterator = std::ostream_iterator; + if (path and depths.find(*path) != depths.end()) { + until = depths.find(*path)->second; + } + if (json.is_object() and depth < until) { + std::size_t i{}; + std::ostringstream oss{}; + oss << '{' << std::endl; + for (auto const& [key, value] : json.items()) { + std::fill_n(iterator{oss}, depth + 1, indent); + oss << nlohmann::json(key).dump() << ": " + << IndentOnlyUntilDepth( + value, + indent, + until, + depth + 1, + path ? std::optional(*path + "/" + key) + : std::nullopt, + depths) + << (++i == json.size() ? "" : ",") << std::endl; + } + std::fill_n(iterator{oss}, depth, indent); + oss << '}'; + gsl_EnsuresAudit(nlohmann::json::parse(oss.str()) == json); + return oss.str(); + } + if (json.is_array() and depth < until) { + std::size_t i{}; + std::ostringstream oss{}; + oss << '[' << std::endl; + for (auto const& value : json) { + std::fill_n(iterator{oss}, depth + 1, indent); + oss << IndentOnlyUntilDepth( + value, indent, until, depth + 1, std::nullopt, depths) + << (++i == json.size() ? "" : ",") << std::endl; + } + std::fill_n(iterator{oss}, depth, indent); + oss << ']'; + gsl_EnsuresAudit(nlohmann::json::parse(oss.str()) == json); + return oss.str(); + } + return json.dump(); +} + } // namespace detail /// \brief Dump json with indent. Indent lists only until specified depth. @@ -81,4 +134,15 @@ namespace detail { json, std::string(indent, ' '), until_depth, 0); } +// \brief Dump json with indent. Indent until the given list; for initial +// pure object-paths, alternative depths can be specified +[[nodiscard]] static inline auto IndentOnlyUntilDepth( + nlohmann::json const& json, + std::size_t indent, + std::size_t until_depth, + std::unordered_map const& depths) -> std::string { + return detail::IndentOnlyUntilDepth( + json, std::string(indent, ' '), until_depth, 0, "", depths); +} + #endif // INCLUDED_SRC_UTILS_CPP_JSON_HPP -- cgit v1.2.3