mirror of
https://github.com/nlohmann/json.git
synced 2026-10-02 12:40:32 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e6257bf49 |
@@ -111,3 +111,12 @@ Linear in the size of the input.
|
||||
- Added in version 3.11.0.
|
||||
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
|
||||
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
||||
|
||||
!!! warning "Deprecation"
|
||||
|
||||
- Overload (2) replaces calls to `from_bjdata` with a pointer and a length as first two parameters, which has been
|
||||
deprecated in version 3.13.0. This overload will be removed in version 4.0.0. Please replace all calls like
|
||||
`#!cpp from_bjdata(ptr, len, ...);` with `#!cpp from_bjdata(ptr, ptr+len, ...);`.
|
||||
|
||||
You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated
|
||||
function.
|
||||
|
||||
@@ -106,3 +106,12 @@ Linear in the size of the input.
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
|
||||
!!! warning "Deprecation"
|
||||
|
||||
- Overload (2) replaces calls to `from_bon8` with a pointer and a length as first two parameters, which has been
|
||||
deprecated in version 3.13.0. This overload will be removed in version 4.0.0. Please replace all calls like
|
||||
`#!cpp from_bon8(ptr, len, ...);` with `#!cpp from_bon8(ptr, ptr+len, ...);`.
|
||||
|
||||
You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated
|
||||
function.
|
||||
|
||||
@@ -50,11 +50,9 @@ The default value is `0` (disabled — existing behavior is preserved).
|
||||
```
|
||||
|
||||
Code that relies on these producing arrays must use `json::array()` instead (see below). Lists with more than one
|
||||
element, and a single `[string, value]` pair *written as a braced list*, such as `{{"key", "value"}}`, which still
|
||||
creates an object, are not affected. This exception is based on how the pair is written, not on the shape of its
|
||||
value: an existing JSON value that happens to be a two-element array with a string as its first element, such as
|
||||
`json arr = {"key", 42};`, is still copied by `json j{arr};` rather than turned into an object. The library's own
|
||||
conversions are not affected either: for example, `std::tuple<int>{5}` still becomes `[5]`.
|
||||
element, and a single `[string, value]` pair such as `{{"key", "value"}}`, which still creates an object, are not
|
||||
affected. The library's own conversions are not affected either: for example, `std::tuple<int>{5}` still becomes
|
||||
`[5]`.
|
||||
|
||||
!!! note "ABI compatibility"
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ class json_ref
|
||||
|
||||
json_ref(std::initializer_list<json_ref> init)
|
||||
: owned_value(init)
|
||||
, braced_list(true)
|
||||
{}
|
||||
|
||||
template <
|
||||
@@ -70,17 +69,9 @@ class json_ref
|
||||
return &** this;
|
||||
}
|
||||
|
||||
/// whether the value was written as a braced list, such as {"key", 1},
|
||||
/// rather than given as a value
|
||||
bool is_braced_list() const noexcept
|
||||
{
|
||||
return braced_list;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable value_type owned_value = nullptr;
|
||||
value_type const* value_ref = nullptr;
|
||||
bool braced_list = false;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
+20
-12
@@ -1672,18 +1672,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
bool type_deduction = true,
|
||||
value_t manual_type = value_t::array)
|
||||
{
|
||||
#if JSON_BRACE_INIT_COPY_SEMANTICS
|
||||
// a single element that is a value rather than a braced list is
|
||||
// copied or moved as is, whatever its content looks like
|
||||
if (type_deduction && init.size() == 1 && !init.begin()->is_braced_list())
|
||||
{
|
||||
*this = init.begin()->moved_or_copied();
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// check if each element is an array with two elements whose first
|
||||
// element is a string
|
||||
bool is_an_object = std::all_of(init.begin(), init.end(),
|
||||
@@ -5559,6 +5547,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.13.0, from_bjdata(ptr, ptr + len))
|
||||
static basic_json from_bjdata(const T* ptr, std::size_t len,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
{
|
||||
return from_bjdata(ptr, ptr + len, strict, allow_exceptions);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in BON8 format
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/from_bon8/
|
||||
template<typename InputType>
|
||||
@@ -5596,6 +5594,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.13.0, from_bon8(ptr, ptr + len))
|
||||
static basic_json from_bon8(const T* ptr, std::size_t len,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
{
|
||||
return from_bon8(ptr, ptr + len, strict, allow_exceptions);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in BSON format
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/from_bson/
|
||||
template<typename InputType>
|
||||
|
||||
@@ -20047,7 +20047,6 @@ class json_ref
|
||||
|
||||
json_ref(std::initializer_list<json_ref> init)
|
||||
: owned_value(init)
|
||||
, braced_list(true)
|
||||
{}
|
||||
|
||||
template <
|
||||
@@ -20083,17 +20082,9 @@ class json_ref
|
||||
return &** this;
|
||||
}
|
||||
|
||||
/// whether the value was written as a braced list, such as {"key", 1},
|
||||
/// rather than given as a value
|
||||
bool is_braced_list() const noexcept
|
||||
{
|
||||
return braced_list;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable value_type owned_value = nullptr;
|
||||
value_type const* value_ref = nullptr;
|
||||
bool braced_list = false;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
@@ -27762,18 +27753,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
bool type_deduction = true,
|
||||
value_t manual_type = value_t::array)
|
||||
{
|
||||
#if JSON_BRACE_INIT_COPY_SEMANTICS
|
||||
// a single element that is a value rather than a braced list is
|
||||
// copied or moved as is, whatever its content looks like
|
||||
if (type_deduction && init.size() == 1 && !init.begin()->is_braced_list())
|
||||
{
|
||||
*this = init.begin()->moved_or_copied();
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// check if each element is an array with two elements whose first
|
||||
// element is a string
|
||||
bool is_an_object = std::all_of(init.begin(), init.end(),
|
||||
@@ -31649,6 +31628,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.13.0, from_bjdata(ptr, ptr + len))
|
||||
static basic_json from_bjdata(const T* ptr, std::size_t len,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
{
|
||||
return from_bjdata(ptr, ptr + len, strict, allow_exceptions);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in BON8 format
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/from_bon8/
|
||||
template<typename InputType>
|
||||
@@ -31686,6 +31675,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.13.0, from_bon8(ptr, ptr + len))
|
||||
static basic_json from_bon8(const T* ptr, std::size_t len,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
{
|
||||
return from_bon8(ptr, ptr + len, strict, allow_exceptions);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in BSON format
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/from_bson/
|
||||
template<typename InputType>
|
||||
|
||||
@@ -4572,3 +4572,31 @@ TEST_CASE("BJData roundtrips" * doctest::skip())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("issue #5648 - from_bjdata(ptr, len) must read len bytes, not treat ptr as a C string")
|
||||
{
|
||||
// to_bjdata() encodes the integer 0 as the two bytes 'i' 0x00 (a BJData
|
||||
// type marker followed by the value byte 0x00), so the packed data
|
||||
// below contains a 0x00 byte before its end.
|
||||
const json j = {{"a", 0}};
|
||||
const std::vector<std::uint8_t> packed = json::to_bjdata(j);
|
||||
bool contains_nul = false;
|
||||
for (const auto byte : packed)
|
||||
{
|
||||
contains_nul |= (byte == 0x00);
|
||||
}
|
||||
REQUIRE(contains_nul);
|
||||
|
||||
// before the fix, from_bjdata had no (ptr, len) overload, so this call
|
||||
// bound to from_bjdata(InputType&&, bool strict) instead: ptr was read
|
||||
// as a NUL-terminated C string (stopping at the embedded 0x00 byte), and
|
||||
// len was silently converted to the strict flag. The deprecated
|
||||
// overload added for this issue forwards to from_bjdata(ptr, ptr + len,
|
||||
// ...) instead, like from_ubjson's deprecated (ptr, len) overload does.
|
||||
json result;
|
||||
CHECK_NOTHROW(result = json::from_bjdata(packed.data(), packed.size()));
|
||||
CHECK(result == j);
|
||||
|
||||
// len must not collapse into the strict flag either
|
||||
CHECK(json::from_bjdata(packed.data(), packed.size(), false) == j);
|
||||
}
|
||||
|
||||
@@ -1010,6 +1010,34 @@ TEST_CASE("BON8 roundtrips" * doctest::skip())
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("issue #5648 - from_bon8(ptr, len) must read len bytes, not treat ptr as a C string")
|
||||
{
|
||||
// to_bon8() encodes the integer 40 as the two bytes 0xC2 0x00 (a BON8
|
||||
// lead byte followed by a continuation byte of 0x00), so the packed data
|
||||
// below contains a 0x00 byte before its end.
|
||||
const json j = {{"a", 40}, {"b", "x"}};
|
||||
const std::vector<std::uint8_t> packed = json::to_bon8(j);
|
||||
bool contains_nul = false;
|
||||
for (const auto byte : packed)
|
||||
{
|
||||
contains_nul |= (byte == 0x00);
|
||||
}
|
||||
REQUIRE(contains_nul);
|
||||
|
||||
// before the fix, from_bon8 had no (ptr, len) overload, so this call
|
||||
// bound to from_bon8(InputType&&, bool strict) instead: ptr was read as
|
||||
// a NUL-terminated C string (stopping at the embedded 0x00 byte), and
|
||||
// len was silently converted to the strict flag. The deprecated
|
||||
// overload added for this issue forwards to from_bon8(ptr, ptr + len,
|
||||
// ...) instead, like from_cbor's deprecated (ptr, len) overload does.
|
||||
json result;
|
||||
CHECK_NOTHROW(result = json::from_bon8(packed.data(), packed.size()));
|
||||
CHECK(result == j);
|
||||
|
||||
// len must not collapse into the strict flag either
|
||||
CHECK(json::from_bon8(packed.data(), packed.size(), false) == j);
|
||||
}
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
TEST_CASE("BON8 with std::byte")
|
||||
{
|
||||
|
||||
@@ -72,28 +72,6 @@ TEST_CASE("JSON_BRACE_INIT_COPY_SEMANTICS")
|
||||
CHECK(j7 == json::array({1, 2}));
|
||||
}
|
||||
|
||||
SECTION("single-element brace initialization copies a pair-shaped array value (#5662)")
|
||||
{
|
||||
// a JSON value that happens to be a 2-element array whose first
|
||||
// element is a string must still be copied, not turned into an
|
||||
// object; only a braced list written in the source, such as the
|
||||
// inner {"key", "value"} of {{"key", "value"}}, describes an object
|
||||
json const pair_shaped = json::array({"key", 42});
|
||||
|
||||
json const j1{pair_shaped};
|
||||
CHECK(j1.is_array());
|
||||
CHECK(j1 == pair_shaped);
|
||||
|
||||
json const j2 = {pair_shaped};
|
||||
CHECK(j2.is_array());
|
||||
CHECK(j2 == pair_shaped);
|
||||
|
||||
// the same holds for an rvalue of the same shape
|
||||
json const j3{json::array({"key", 42})};
|
||||
CHECK(j3.is_array());
|
||||
CHECK(j3 == pair_shaped);
|
||||
}
|
||||
|
||||
SECTION("what the macro does not change")
|
||||
{
|
||||
// lists with more than one element are unaffected
|
||||
|
||||
Reference in New Issue
Block a user