mirror of
https://github.com/nlohmann/json.git
synced 2026-10-01 20:20:32 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2add64396a |
@@ -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"
|
||||
|
||||
|
||||
@@ -975,10 +975,15 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
case '\n':
|
||||
case '\r':
|
||||
case char_traits<char_type>::eof():
|
||||
return true;
|
||||
|
||||
#if !JSON_STRICT_NUL_HANDLING
|
||||
case '\0':
|
||||
#endif
|
||||
// a NUL byte is the end of the input (see scan()),
|
||||
// so leave it for scan() to see
|
||||
unget();
|
||||
return true;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -10067,10 +10067,15 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
case '\n':
|
||||
case '\r':
|
||||
case char_traits<char_type>::eof():
|
||||
return true;
|
||||
|
||||
#if !JSON_STRICT_NUL_HANDLING
|
||||
case '\0':
|
||||
#endif
|
||||
// a NUL byte is the end of the input (see scan()),
|
||||
// so leave it for scan() to see
|
||||
unget();
|
||||
return true;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -20047,7 +20052,6 @@ class json_ref
|
||||
|
||||
json_ref(std::initializer_list<json_ref> init)
|
||||
: owned_value(init)
|
||||
, braced_list(true)
|
||||
{}
|
||||
|
||||
template <
|
||||
@@ -20083,17 +20087,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 +27758,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(),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -592,6 +592,45 @@ TEST_CASE("parser class")
|
||||
|
||||
// parsing from a string literal is unaffected either way
|
||||
CHECK(json::parse("123") == json(123));
|
||||
|
||||
// a NUL byte that ends a // comment ends the input just
|
||||
// like a NUL byte anywhere else (issue #5659); before the
|
||||
// fix, the NUL was consumed as part of the comment, and
|
||||
// scanning continued with whatever followed it
|
||||
{
|
||||
// same as "//c" alone (real end of input after the
|
||||
// comment), rather than continuing with "[1]"
|
||||
std::string s1 = "//c";
|
||||
s1.push_back('\0');
|
||||
s1 += "[1]";
|
||||
json _; // NOLINT(readability-identifier-naming)
|
||||
CHECK_THROWS_WITH_AS(_ = json::parse(s1, nullptr, true, true),
|
||||
"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal",
|
||||
json::parse_error&);
|
||||
CHECK_FALSE(json::accept(s1, true, true));
|
||||
}
|
||||
|
||||
{
|
||||
// same as "[1, //c" alone, rather than continuing with " 2]"
|
||||
std::string s2 = "[1, //c";
|
||||
s2.push_back('\0');
|
||||
s2 += " 2]";
|
||||
json _; // NOLINT(readability-identifier-naming)
|
||||
CHECK_THROWS_WITH_AS(_ = json::parse(s2, nullptr, true, true),
|
||||
"[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal",
|
||||
json::parse_error&);
|
||||
CHECK_FALSE(json::accept(s2, true, true));
|
||||
}
|
||||
|
||||
{
|
||||
// same as "1 //c" alone: the comment (and the NUL that
|
||||
// ends it) is ignored, and "x" is never reached
|
||||
std::string s3 = "1 //c";
|
||||
s3.push_back('\0');
|
||||
s3 += "x";
|
||||
CHECK(json::parse(s3, nullptr, true, true) == json(1));
|
||||
CHECK(json::accept(s3, true, true));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user