Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26700c6dc3 | ||
|
|
b9a581e6d2 | ||
|
|
0bd2d36f2a | ||
|
|
a2ca07a4b3 | ||
|
|
cda8d2b848 | ||
|
|
db1d0983e6 |
No files matched your search
@@ -137,10 +137,13 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
|||||||
|
|
||||||
When the JSON pointer traverses intermediate levels that don't exist at all yet (not just a missing
|
When the JSON pointer traverses intermediate levels that don't exist at all yet (not just a missing
|
||||||
leaf), each missing level is created as an array or an object depending on whether the corresponding
|
leaf), each missing level is created as an array or an object depending on whether the corresponding
|
||||||
pointer token parses as a non-negative integer: a numeric token creates an array, a non-numeric token
|
pointer token is a valid array index: the token `0`, a sequence of digits that does not begin with `0`,
|
||||||
creates an object. For example, on an initially `#!json null` value, `/foo/0/0/0` creates nested arrays,
|
or the token `-` creates an array, and every other token creates an object. For example, on an
|
||||||
while `/foo/one/one/one` creates nested objects. This is not specified by the JSON Pointer RFC; it is
|
initially `#!json null` value, `/foo/0/0/0` creates nested arrays, while `/foo/one/one/one` creates
|
||||||
this library's own, intentional disambiguation rule. See also [JSON Pointer](../../features/json_pointer.md).
|
nested objects. Tokens such as `01` or the empty token cannot be array indices (cf. RFC 6901, Sect. 4)
|
||||||
|
and therefore create objects, just as they would if the level already existed as an object. This is not
|
||||||
|
specified by the JSON Pointer RFC; it is this library's own, intentional disambiguation rule. See also
|
||||||
|
[JSON Pointer](../../features/json_pointer.md).
|
||||||
|
|
||||||
!!! warning "Deprecation"
|
!!! warning "Deprecation"
|
||||||
|
|
||||||
|
|||||||
@@ -473,15 +473,19 @@ class json_pointer
|
|||||||
// convert null values to arrays or objects before continuing
|
// convert null values to arrays or objects before continuing
|
||||||
if (ptr->is_null())
|
if (ptr->is_null())
|
||||||
{
|
{
|
||||||
// check if the reference token is a number
|
// check if the reference token is a valid array index, that is
|
||||||
const bool nums =
|
// a nonempty sequence of digits without a leading '0'
|
||||||
std::all_of(reference_token.begin(), reference_token.end(),
|
// (cf. RFC 6901, Sect. 4); tokens that could never be a valid
|
||||||
[](const unsigned char x)
|
// array index (such as "01" or "") are treated as object keys
|
||||||
|
const bool nums = !reference_token.empty()
|
||||||
|
&& (reference_token.size() == 1 || reference_token[0] != '0')
|
||||||
|
&& std::all_of(reference_token.begin(), reference_token.end(),
|
||||||
|
[](const unsigned char x)
|
||||||
{
|
{
|
||||||
return std::isdigit(x);
|
return std::isdigit(x);
|
||||||
});
|
});
|
||||||
|
|
||||||
// change value to an array for numbers or "-" or to object otherwise
|
// change value to an array for array indices or "-" or to object otherwise
|
||||||
*ptr = (nums || reference_token == "-")
|
*ptr = (nums || reference_token == "-")
|
||||||
? detail::value_t::array
|
? detail::value_t::array
|
||||||
: detail::value_t::object;
|
: detail::value_t::object;
|
||||||
|
|||||||
@@ -20391,15 +20391,19 @@ class json_pointer
|
|||||||
// convert null values to arrays or objects before continuing
|
// convert null values to arrays or objects before continuing
|
||||||
if (ptr->is_null())
|
if (ptr->is_null())
|
||||||
{
|
{
|
||||||
// check if the reference token is a number
|
// check if the reference token is a valid array index, that is
|
||||||
const bool nums =
|
// a nonempty sequence of digits without a leading '0'
|
||||||
std::all_of(reference_token.begin(), reference_token.end(),
|
// (cf. RFC 6901, Sect. 4); tokens that could never be a valid
|
||||||
[](const unsigned char x)
|
// array index (such as "01" or "") are treated as object keys
|
||||||
|
const bool nums = !reference_token.empty()
|
||||||
|
&& (reference_token.size() == 1 || reference_token[0] != '0')
|
||||||
|
&& std::all_of(reference_token.begin(), reference_token.end(),
|
||||||
|
[](const unsigned char x)
|
||||||
{
|
{
|
||||||
return std::isdigit(x);
|
return std::isdigit(x);
|
||||||
});
|
});
|
||||||
|
|
||||||
// change value to an array for numbers or "-" or to object otherwise
|
// change value to an array for array indices or "-" or to object otherwise
|
||||||
*ptr = (nums || reference_token == "-")
|
*ptr = (nums || reference_token == "-")
|
||||||
? detail::value_t::array
|
? detail::value_t::array
|
||||||
: detail::value_t::object;
|
: detail::value_t::object;
|
||||||
|
|||||||
@@ -466,6 +466,72 @@ TEST_CASE("JSON pointers")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("creating intermediate levels")
|
||||||
|
{
|
||||||
|
SECTION("tokens that are valid array indices create arrays")
|
||||||
|
{
|
||||||
|
json j;
|
||||||
|
j["/0"_json_pointer] = 1;
|
||||||
|
CHECK(j == json({1}));
|
||||||
|
|
||||||
|
json j2;
|
||||||
|
j2["/2"_json_pointer] = 1;
|
||||||
|
CHECK(j2 == json({nullptr, nullptr, 1}));
|
||||||
|
|
||||||
|
json j3;
|
||||||
|
j3["/-"_json_pointer] = 1;
|
||||||
|
CHECK(j3 == json({1}));
|
||||||
|
|
||||||
|
json j4;
|
||||||
|
j4["/foo/0/0"_json_pointer] = 1;
|
||||||
|
CHECK(j4 == json({{"foo", {{1}}}}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("tokens that are no valid array indices create objects")
|
||||||
|
{
|
||||||
|
json j;
|
||||||
|
j["/one"_json_pointer] = 1;
|
||||||
|
CHECK(j == json({{"one", 1}}));
|
||||||
|
|
||||||
|
// leading '0' can never be a valid array index (RFC 6901, Sect. 4)
|
||||||
|
json j2;
|
||||||
|
j2["/01"_json_pointer] = 1;
|
||||||
|
CHECK(j2 == json({{"01", 1}}));
|
||||||
|
|
||||||
|
// the empty token is a valid object key, but no valid array index
|
||||||
|
json j3;
|
||||||
|
j3["/"_json_pointer] = 1;
|
||||||
|
CHECK(j3 == json({{"", 1}}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("creating a level yields the same result as reusing it (#5357)")
|
||||||
|
{
|
||||||
|
json j;
|
||||||
|
j["/a/b/01/d"_json_pointer] = "value";
|
||||||
|
|
||||||
|
json j_init = json::object();
|
||||||
|
j_init["/a/b"_json_pointer] = json::object();
|
||||||
|
j_init["/a/b/01/d"_json_pointer] = "value";
|
||||||
|
|
||||||
|
const json expected = json::parse(R"({"a":{"b":{"01":{"d":"value"}}}})");
|
||||||
|
CHECK(j == expected);
|
||||||
|
CHECK(j_init == expected);
|
||||||
|
|
||||||
|
// unflatten uses the same key
|
||||||
|
const json flat = {{"/a/b/01/d", "value"}};
|
||||||
|
CHECK(flat.unflatten() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("existing arrays still reject invalid indices")
|
||||||
|
{
|
||||||
|
json j = {1, 2, 3};
|
||||||
|
CHECK_THROWS_WITH_AS(j["/01"_json_pointer],
|
||||||
|
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'", json::parse_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(j.at("/01"_json_pointer),
|
||||||
|
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'", json::parse_error&);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("flatten")
|
SECTION("flatten")
|
||||||
{
|
{
|
||||||
json j =
|
json j =
|
||||||
|
|||||||
Reference in new issue
Block a user