diff options
author | Klaus Aehlig <klaus.aehlig@huawei.com> | 2022-04-25 15:22:07 +0200 |
---|---|---|
committer | Klaus Aehlig <klaus.aehlig@huawei.com> | 2022-04-25 15:33:04 +0200 |
commit | cafea2acc444692e7fe99292a73a7fbc0f1ec348 (patch) | |
tree | e24b260314edf68d5eff0174f57fb33e1eb024b7 /src/utils/cpp/json.hpp | |
parent | 32322ff28c151d8ec5510b7019365d573e44bddf (diff) | |
download | justbuild-cafea2acc444692e7fe99292a73a7fbc0f1ec348.tar.gz |
json utils: support indentation up to a given depth
Diffstat (limited to 'src/utils/cpp/json.hpp')
-rw-r--r-- | src/utils/cpp/json.hpp | 64 |
1 files changed, 64 insertions, 0 deletions
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 <optional> #include <sstream> #include <string> +#include <unordered_map> #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<std::string> path, + std::unordered_map<std::string, std::size_t> const& depths) -> std::string { + using iterator = std::ostream_iterator<std::string>; + 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<std::string>(*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<std::string, std::size_t> const& depths) -> std::string { + return detail::IndentOnlyUntilDepth( + json, std::string(indent, ' '), until_depth, 0, "", depths); +} + #endif // INCLUDED_SRC_UTILS_CPP_JSON_HPP |