Merge branch 'json-view/08-view-builder' into json-view/10-view-document

Conflicts in the See also lists of nine basic_json pages, is_discarded.md, and features/index.md, where develop (#5638) and this branch both added entries: kept both. Ran make amalgamate.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-10-02 11:36:41 +02:00
301 changed files with 5560 additions and 697 deletions
+57 -29
View File
@@ -2710,7 +2710,7 @@ void templated_json_throw(ExceptionType exception)
@brief macro to briefly define a mapping between an enum and JSON with exception
on invalid input
@def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT
@since version 3.12.0
@since version 3.13.0
*/
#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \
template<typename BasicJsonType> \
@@ -6261,7 +6261,7 @@ inline std::string hex_byte(const std::uint8_t byte)
Used to turn a decoded code point back into bytes: by the wide-string input
adapters in input_adapters.hpp (one code point per UTF-32 unit, per UTF-16
unit outside the surrogate range, and per valid UTF-16 surrogate pair), and
by the lexer's `\uXXXX`/`\uXXXX\uYYYY` handling in lexer.hpp. Passing a
by the lexer's handling of u-escapes and surrogate pairs in lexer.hpp. Passing a
code point above U+10FFFF, or one in the surrogate range U+D800..U+DFFF, is
undefined behavior; callers are expected to have rejected those already
(the wide-string adapters pass malformed units through unencoded instead of
@@ -6274,7 +6274,7 @@ reaching it).
@param[in] out called once for each byte of the UTF-8 encoding of @a cp
*/
template<typename Out>
void encode_utf8(std::uint32_t cp, Out&& out)
void encode_utf8(std::uint32_t cp, const Out& out)
{
JSON_ASSERT(cp <= 0x10FFFF);
@@ -6848,8 +6848,11 @@ struct external_constructor<value_t::array>
for (auto&& x : std::forward<CompatibleArrayType>(arr))
{
j.m_data.m_value.array->push_back(x);
j.set_parent(j.m_data.m_value.array->back());
}
// set the parents only once all elements are in place: a push_back
// that reallocates moves the earlier elements, which does not keep
// their parent pointers
j.set_parents();
j.assert_invariant();
}
#endif
@@ -14604,13 +14607,13 @@ class binary_reader
case 0x10: // int32
{
std::int32_t value{};
return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(conditional_static_cast<number_integer_t>(value));
}
case 0x12: // int64
{
std::int64_t value{};
return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(conditional_static_cast<number_integer_t>(value));
}
case 0x11: // uint64
@@ -14649,7 +14652,7 @@ class binary_reader
parse_error::create(112, chars_read,
exception_message(input_format_t::cbor, "negative integer overflow", "value"), nullptr));
}
return sax->number_integer(static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(number));
return sax->number_integer(conditional_static_cast<number_integer_t>(static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(number)));
}
/*!
@@ -15895,25 +15898,25 @@ class binary_reader
case 0xD0: // int 8
{
std::int8_t number{};
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
return get_number(input_format_t::msgpack, number) && sax->number_integer(conditional_static_cast<number_integer_t>(number));
}
case 0xD1: // int 16
{
std::int16_t number{};
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
return get_number(input_format_t::msgpack, number) && sax->number_integer(conditional_static_cast<number_integer_t>(number));
}
case 0xD2: // int 32
{
std::int32_t number{};
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
return get_number(input_format_t::msgpack, number) && sax->number_integer(conditional_static_cast<number_integer_t>(number));
}
case 0xD3: // int 64
{
std::int64_t number{};
return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
return get_number(input_format_t::msgpack, number) && sax->number_integer(conditional_static_cast<number_integer_t>(number));
}
case 0xDC: // array 16
@@ -16970,25 +16973,25 @@ class binary_reader
case 'i':
{
std::int8_t number{};
return get_number(input_format, number) && sax->number_integer(number);
return get_number(input_format, number) && sax->number_integer(conditional_static_cast<number_integer_t>(number));
}
case 'I':
{
std::int16_t number{};
return get_number(input_format, number) && sax->number_integer(number);
return get_number(input_format, number) && sax->number_integer(conditional_static_cast<number_integer_t>(number));
}
case 'l':
{
std::int32_t number{};
return get_number(input_format, number) && sax->number_integer(number);
return get_number(input_format, number) && sax->number_integer(conditional_static_cast<number_integer_t>(number));
}
case 'L':
{
std::int64_t number{};
return get_number(input_format, number) && sax->number_integer(number);
return get_number(input_format, number) && sax->number_integer(conditional_static_cast<number_integer_t>(number));
}
case 'u':
@@ -17548,7 +17551,7 @@ class binary_reader
// integer -1..-10
if (byte <= 0xC1)
{
return sax->number_integer(-1 - static_cast<number_integer_t>(byte - 0xB8));
return sax->number_integer(conditional_static_cast<number_integer_t>(-1 - static_cast<number_integer_t>(byte - 0xB8)));
}
// 0xC2..0xF7: a UTF-8 lead byte begins a string if a continuation
@@ -17678,6 +17681,11 @@ class binary_reader
if (0xC2 <= byte && byte <= 0xF7)
{
const auto second = get_bon8();
if (second == char_traits<char_type>::eof())
{
// the input ends inside a character or an integer
return unexpect_eof(input_format_t::bon8, "key");
}
unget_bon8(second);
if (is_bon8_continuation(second))
{
@@ -17776,6 +17784,12 @@ class binary_reader
// a lead byte ends the string if no continuation byte follows: it
// is then the first byte of an integer
const auto second = get_bon8();
if (second == char_traits<char_type>::eof())
{
// the input ends inside a character or an integer: either
// way, the message is incomplete
return unexpect_eof(input_format_t::bon8, "string");
}
if (!is_bon8_continuation(second))
{
unget_bon8(second);
@@ -17856,6 +17870,8 @@ class binary_reader
template<class T>
bool get_to(T& dest, const input_format_t format, const char* context)
{
// false positive: new_chars_read is read on the next lines
// @infer-ignore DEAD_STORE
auto new_chars_read = ia.get_elements(&dest);
chars_read += new_chars_read;
if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
@@ -18107,6 +18123,8 @@ class binary_reader
// resize() is required to make size() exactly old_size + wanted;
// that is the room get_elements() is allowed to write into
JSON_ASSERT(result.size() == old_size + wanted);
// false positive: bytes_read is read on the next lines
// @infer-ignore DEAD_STORE
const std::size_t bytes_read = ia.get_elements(&result[old_size], wanted);
chars_read += bytes_read;
if (JSON_HEDLEY_UNLIKELY(bytes_read < wanted))
@@ -18363,8 +18381,9 @@ using parser_callback_t =
/*!
@brief syntax analysis
This class implements an iterative parser that keeps the open containers on
an explicit stack and reports what it reads as SAX events.
This class implements a parser for JSON text. Nested arrays and objects are tracked with an explicit
stack instead of recursion, so deeply nested input does not exhaust the call stack, and what is read
is reported as SAX events.
*/
template<typename BasicJsonType, typename InputAdapterType>
class parser
@@ -20105,7 +20124,7 @@ class json_pointer
}
/// @brief return a string representation of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
/// @sa https://json.nlohmann.me/api/json_pointer/operator_string_t/
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
operator string_t() const
{
@@ -20114,7 +20133,7 @@ class json_pointer
#ifndef JSON_NO_IO
/// @brief write string representation of the JSON pointer to stream
/// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
/// @sa https://json.nlohmann.me/api/operator_ltlt/
friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
{
o << ptr.to_string();
@@ -21126,7 +21145,8 @@ class json_pointer
friend bool operator!=(const StringType& lhs,
const json_pointer<RefStringTypeRhs>& rhs);
/// @brief compares two JSON pointer for less-than
/// @brief compares two JSON pointers for less-than
/// @sa https://json.nlohmann.me/api/json_pointer/operator_spaceship/
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
@@ -26787,12 +26807,13 @@ NLOHMANN_JSON_NAMESPACE_END
#include <functional> // equal_to, less
#include <initializer_list> // initializer_list
#include <iterator> // input_iterator_tag, iterator_traits
#include <memory> // allocator
#include <new> // for operator new (placement new)
#include <stdexcept> // for out_of_range
#include <tuple> // forward_as_tuple
#include <type_traits> // enable_if, integral_constant, is_convertible, is_nothrow_move_constructible
#include <utility> // forward, move, pair, piecewise_construct
#include <vector> // vector, allocator
#include <vector> // vector
// #include <nlohmann/detail/abi_macros.hpp>
@@ -32283,7 +32304,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @{
#ifndef JSON_NO_IO
/// @brief serialize to stream
/// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
/// @sa https://json.nlohmann.me/api/operator_ltlt/
friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
{
// read width member and use it as the indentation parameter if nonzero
@@ -32302,7 +32323,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
/// @brief serialize to stream
/// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
/// @sa https://json.nlohmann.me/api/operator_ltlt/
/// @deprecated This function is deprecated since 3.0.0 and will be removed in
/// version 4.0.0 of the library. Please use
/// operator<<(std::ostream&, const basic_json&) instead; that is,
@@ -32471,7 +32492,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
#endif
#ifndef JSON_NO_IO
/// @brief deserialize from stream
/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
/// @sa https://json.nlohmann.me/api/operator_gtgt/
/// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
/// version 4.0.0 of the library. Please use
/// operator>>(std::istream&, basic_json&) instead; that is,
@@ -32483,7 +32504,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
/// @brief deserialize from stream
/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
/// @sa https://json.nlohmann.me/api/operator_gtgt/
friend std::istream& operator>>(std::istream& i, basic_json& j)
{
// parse into a temporary so that j is left unchanged if parsing fails
@@ -33679,6 +33700,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// Any other object type places its members itself - std::map
// in key order, a hash map in an order its operator== ignores -
// so a member-by-member diff always reproduces target there.
#ifdef JSON_HEDLEY_MSVC_VERSION
#pragma warning(push )
#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
#endif
if (!detail::is_ordered_map<object_t>::value
|| (common_keys_source_order == common_keys_target_order && new_keys_form_suffix))
{
@@ -33689,6 +33714,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
common_keys = std::move(common_keys_source_order);
return true;
}
#ifdef JSON_HEDLEY_MSVC_VERSION
#pragma warning( pop )
#endif
// slow path: the common keys are in a different relative
// order in source and target (only possible for a
@@ -34185,10 +34213,10 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
int indent = -1;
char indent_char = ' ';
constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator
constexpr format_parse_context::iterator parse(format_parse_context& ctx)
{
auto it = ctx.begin();
const auto end = ctx.end();
format_parse_context::iterator it = ctx.begin();
const format_parse_context::iterator end = ctx.end();
constexpr auto is_align = [](char c)
{
return c == '<' || c == '>' || c == '^';