mirror of
https://github.com/nlohmann/json.git
synced 2026-09-30 19:50:34 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc6d74feb0 |
@@ -50,9 +50,11 @@ 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
|
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 such as `{{"key", "value"}}`, which still creates an object, are not
|
element, and a single `[string, value]` pair *written as a braced list*, such as `{{"key", "value"}}`, which still
|
||||||
affected. The library's own conversions are not affected either: for example, `std::tuple<int>{5}` still becomes
|
creates an object, are not affected. This exception is based on how the pair is written, not on the shape of its
|
||||||
`[5]`.
|
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]`.
|
||||||
|
|
||||||
!!! note "ABI compatibility"
|
!!! note "ABI compatibility"
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ class json_ref
|
|||||||
|
|
||||||
json_ref(std::initializer_list<json_ref> init)
|
json_ref(std::initializer_list<json_ref> init)
|
||||||
: owned_value(init)
|
: owned_value(init)
|
||||||
|
, braced_list(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
@@ -69,9 +70,17 @@ class json_ref
|
|||||||
return &** this;
|
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:
|
private:
|
||||||
mutable value_type owned_value = nullptr;
|
mutable value_type owned_value = nullptr;
|
||||||
value_type const* value_ref = nullptr;
|
value_type const* value_ref = nullptr;
|
||||||
|
bool braced_list = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@@ -1672,6 +1672,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
bool type_deduction = true,
|
bool type_deduction = true,
|
||||||
value_t manual_type = value_t::array)
|
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
|
// check if each element is an array with two elements whose first
|
||||||
// element is a string
|
// element is a string
|
||||||
bool is_an_object = std::all_of(init.begin(), init.end(),
|
bool is_an_object = std::all_of(init.begin(), init.end(),
|
||||||
|
|||||||
@@ -20047,6 +20047,7 @@ class json_ref
|
|||||||
|
|
||||||
json_ref(std::initializer_list<json_ref> init)
|
json_ref(std::initializer_list<json_ref> init)
|
||||||
: owned_value(init)
|
: owned_value(init)
|
||||||
|
, braced_list(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
@@ -20082,9 +20083,17 @@ class json_ref
|
|||||||
return &** this;
|
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:
|
private:
|
||||||
mutable value_type owned_value = nullptr;
|
mutable value_type owned_value = nullptr;
|
||||||
value_type const* value_ref = nullptr;
|
value_type const* value_ref = nullptr;
|
||||||
|
bool braced_list = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@@ -27753,6 +27762,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
bool type_deduction = true,
|
bool type_deduction = true,
|
||||||
value_t manual_type = value_t::array)
|
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
|
// check if each element is an array with two elements whose first
|
||||||
// element is a string
|
// element is a string
|
||||||
bool is_an_object = std::all_of(init.begin(), init.end(),
|
bool is_an_object = std::all_of(init.begin(), init.end(),
|
||||||
|
|||||||
@@ -72,6 +72,28 @@ TEST_CASE("JSON_BRACE_INIT_COPY_SEMANTICS")
|
|||||||
CHECK(j7 == json::array({1, 2}));
|
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")
|
SECTION("what the macro does not change")
|
||||||
{
|
{
|
||||||
// lists with more than one element are unaffected
|
// lists with more than one element are unaffected
|
||||||
|
|||||||
Reference in New Issue
Block a user