Allow value(json_pointer) to work with arrays as documented

pull/3759/head
Florian Albrechtskirchinger 2022-09-20 16:08:54 +02:00
parent f4658de270
commit 6724d9450f
No known key found for this signature in database
GPG Key ID: 19618CE9B2D4BE6D
4 changed files with 49 additions and 14 deletions

View File

@ -94,8 +94,20 @@ changes to any JSON value.
3. The function can throw the following exceptions:
- Throws [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) if `default_value` does not match
the type of the value at `ptr`
- Throws [`type_error.306`](../../home/exceptions.md#jsonexceptiontype_error306) if the JSON value is not an object;
in that case, using `value()` with a key makes no sense.
- Throws [`type_error.306`](../../home/exceptions.md#jsonexceptiontype_error306) if the JSON value is not an array
or object; in that case, using `value()` with a key makes no sense.
- Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index in the passed
JSON pointer `ptr` begins with '0'.
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in the passed
JSON pointer `ptr` is not a number.
- Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if an array index in the passed
JSON pointer `ptr` is out of range.
- Throws [`out_of_range.402`](../../home/exceptions.md#jsonexceptionout_of_range402) if the array index '-' is used
in the passed JSON pointer `ptr`.
- Throws [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if the JSON pointer describes a
key of an object which cannot be found. See example below.
- Throws [`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) if the JSON pointer `ptr` can
not be resolved. See example below.
## Complexity

View File

@ -2320,8 +2320,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
ValueType value(const json_pointer& ptr, const ValueType& default_value) const
{
// value only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
// value only works for arrays and objects
if (JSON_HEDLEY_LIKELY(is_structured()))
{
// if pointer resolves a value, return it or use default value
JSON_TRY
@ -2345,8 +2345,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
ReturnType value(const json_pointer& ptr, ValueType && default_value) const
{
// value only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
// value only works for arrays and objects
if (JSON_HEDLEY_LIKELY(is_structured()))
{
// if pointer resolves a value, return it or use default value
JSON_TRY

View File

@ -21536,8 +21536,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
ValueType value(const json_pointer& ptr, const ValueType& default_value) const
{
// value only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
// value only works for arrays and objects
if (JSON_HEDLEY_LIKELY(is_structured()))
{
// if pointer resolves a value, return it or use default value
JSON_TRY
@ -21561,8 +21561,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
ReturnType value(const json_pointer& ptr, ValueType && default_value) const
{
// value only works for objects
if (JSON_HEDLEY_LIKELY(is_object()))
// value only works for arrays and objects
if (JSON_HEDLEY_LIKELY(is_structured()))
{
// if pointer resolves a value, return it or use default value
JSON_TRY

View File

@ -423,10 +423,33 @@ TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_j
SECTION("array")
{
Json j_nonobject(Json::value_t::array);
const Json j_nonobject_const(Json::value_t::array);
CHECK_THROWS_WITH_AS(j_nonobject.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with array", typename Json::type_error&);
CHECK_THROWS_WITH_AS(j_nonobject_const.value("/foo"_json_pointer, 1), "[json.exception.type_error.306] cannot use value() with array", typename Json::type_error&);
Json j_array = Json::array({j});
const Json j_array_const = Json::array({j});
CHECK(j_array.value("/0/integer"_json_pointer, 2) == 1);
CHECK(j_array.value("/0/integer"_json_pointer, 1.0) == Approx(1));
CHECK(j_array.value("/0/unsigned"_json_pointer, 2) == 1u);
CHECK(j_array.value("/0/unsigned"_json_pointer, 1.0) == Approx(1u));
CHECK(j_array.value("/0/null"_json_pointer, Json(1)) == Json());
CHECK(j_array.value("/0/boolean"_json_pointer, false) == true);
CHECK(j_array.value("/0/string"_json_pointer, "bar") == "hello world");
CHECK(j_array.value("/0/string"_json_pointer, std::string("bar")) == "hello world");
CHECK(j_array.value("/0/floating"_json_pointer, 12.34) == Approx(42.23));
CHECK(j_array.value("/0/floating"_json_pointer, 12) == 42);
CHECK(j_array.value("/0/object"_json_pointer, Json({{"foo", "bar"}})) == Json::object());
CHECK(j_array.value("/0/array"_json_pointer, Json({10, 100})) == Json({1, 2, 3}));
CHECK(j_array_const.value("/0/integer"_json_pointer, 2) == 1);
CHECK(j_array_const.value("/0/integer"_json_pointer, 1.0) == Approx(1));
CHECK(j_array_const.value("/0/unsigned"_json_pointer, 2) == 1u);
CHECK(j_array_const.value("/0/unsigned"_json_pointer, 1.0) == Approx(1u));
CHECK(j_array_const.value("/0/boolean"_json_pointer, false) == true);
CHECK(j_array_const.value("/0/string"_json_pointer, "bar") == "hello world");
CHECK(j_array_const.value("/0/string"_json_pointer, std::string("bar")) == "hello world");
CHECK(j_array_const.value("/0/floating"_json_pointer, 12.34) == Approx(42.23));
CHECK(j_array_const.value("/0/floating"_json_pointer, 12) == 42);
CHECK(j_array_const.value("/0/object"_json_pointer, Json({{"foo", "bar"}})) == Json::object());
CHECK(j_array_const.value("/0/array"_json_pointer, Json({10, 100})) == Json({1, 2, 3}));
}
SECTION("number (integer)")