mirror of
https://github.com/nlohmann/json.git
synced 2026-07-03 17:24:18 +00:00
Add std::format and fmt support (#5224)
* ✨ add std::format and fmt support Signed-off-by: Niels Lohmann <mail@nlohmann.me> * ♻️ reorganize PR Signed-off-by: Niels Lohmann <mail@nlohmann.me> * 💚 fix build Signed-off-by: Niels Lohmann <mail@nlohmann.me> * 💚 fix build Signed-off-by: Niels Lohmann <mail@nlohmann.me> * 💚 fix build Signed-off-by: Niels Lohmann <mail@nlohmann.me> --------- Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
@@ -79,6 +79,10 @@
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
#if JSON_HAS_STD_FORMAT
|
||||
#include <format> // format_parse_context, format_context, formatter, format_error
|
||||
#endif
|
||||
|
||||
/*!
|
||||
@brief namespace for Niels Lohmann
|
||||
@see https://github.com/nlohmann
|
||||
@@ -5258,6 +5262,14 @@ std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
|
||||
return j.dump();
|
||||
}
|
||||
|
||||
/// @brief user-defined format_as function for JSON values (fmt <= 11.0.x support)
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/format_as/
|
||||
NLOHMANN_BASIC_JSON_TPL_DECLARATION
|
||||
std::string format_as(const NLOHMANN_BASIC_JSON_TPL& j)
|
||||
{
|
||||
return j.dump();
|
||||
}
|
||||
|
||||
inline namespace literals
|
||||
{
|
||||
inline namespace json_literals
|
||||
@@ -5361,6 +5373,84 @@ inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC
|
||||
|
||||
#endif
|
||||
|
||||
#if JSON_HAS_STD_FORMAT
|
||||
|
||||
/// @brief std::formatter specialization for JSON values
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/std_formatter/
|
||||
NLOHMANN_BASIC_JSON_TPL_DECLARATION
|
||||
struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-cpp)
|
||||
{
|
||||
// -1 means compact output (dump()); any value >= 0 means pretty-printed
|
||||
// output with that many spaces (or indent_char) per level (dump(indent, indent_char)).
|
||||
int indent = -1;
|
||||
char indent_char = ' ';
|
||||
|
||||
constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator
|
||||
{
|
||||
auto it = ctx.begin();
|
||||
const auto end = ctx.end();
|
||||
constexpr auto is_align = [](char c)
|
||||
{
|
||||
return c == '<' || c == '>' || c == '^';
|
||||
};
|
||||
|
||||
// [[fill] align] - repurposed here to pick a custom indent character,
|
||||
// e.g. "{:.>#4}" pretty-prints with '.' as the indent character
|
||||
if (it != end && it + 1 != end && is_align(it[1]))
|
||||
{
|
||||
indent_char = *it;
|
||||
it += 2;
|
||||
}
|
||||
else if (it != end && is_align(*it))
|
||||
{
|
||||
++it;
|
||||
}
|
||||
|
||||
// ['#'] - "alternate form", used here to request pretty-printing with a
|
||||
// default indent of 4 (overridden by an explicit width below, if given)
|
||||
if (it != end && *it == '#')
|
||||
{
|
||||
indent = 4;
|
||||
++it;
|
||||
}
|
||||
|
||||
// [width] - repurposed here to pick the indent size for pretty-printing,
|
||||
// e.g. "{:2}" or "{:#2}" pretty-print with an indent of 2; a width without
|
||||
// '#' implies pretty-printing since an indent otherwise has no meaning
|
||||
if (it != end && *it >= '1' && *it <= '9')
|
||||
{
|
||||
indent = 0;
|
||||
while (it != end && *it >= '0' && *it <= '9')
|
||||
{
|
||||
indent = (indent * 10) + (*it - '0');
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// sign, the '0' flag, precision, locale-specific formatting ('L'), dynamic
|
||||
// width/precision ("{...}"), and type characters all have no meaning for
|
||||
// JSON values; none of them are consumed above, so they all end up rejected
|
||||
// by this single check along with any other unrecognized trailing spec.
|
||||
if (it != end && *it != '}')
|
||||
{
|
||||
JSON_THROW(format_error("invalid format args for nlohmann::json"));
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
template<typename FormatContext>
|
||||
auto format(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j, FormatContext& ctx) const -> decltype(ctx.out())
|
||||
{
|
||||
// dump()'s own default (indent = -1) already means compact output, so this
|
||||
// covers both the compact and pretty-printed cases without a branch.
|
||||
const auto dumped = j.dump(indent, indent_char);
|
||||
return std::copy(dumped.begin(), dumped.end(), ctx.out());
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace std
|
||||
|
||||
#if JSON_USE_GLOBAL_UDLS
|
||||
|
||||
Reference in New Issue
Block a user