diff --git a/docs/mkdocs/docs/api/basic_json/value.md b/docs/mkdocs/docs/api/basic_json/value.md index c9bca6be7..598ce0798 100644 --- a/docs/mkdocs/docs/api/basic_json/value.md +++ b/docs/mkdocs/docs/api/basic_json/value.md @@ -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 diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 55ec39d24..5aa64748a 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -2354,8 +2354,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec && !std::is_same>::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 the pointer resolves to a value, return it. Otherwise, return // 'default_value'. @@ -2380,8 +2380,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec && !std::is_same>::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 the pointer resolves to a value, return it. Otherwise, return // 'default_value'. diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 919b5fc43..c359253da 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -22456,8 +22456,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec && !std::is_same>::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 the pointer resolves to a value, return it. Otherwise, return // 'default_value'. @@ -22482,8 +22482,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec && !std::is_same>::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 the pointer resolves to a value, return it. Otherwise, return // 'default_value'. diff --git a/tests/src/unit-element_access2.cpp b/tests/src/unit-element_access2.cpp index 61984ddf6..158c109ed 100644 --- a/tests/src/unit-element_access2.cpp +++ b/tests/src/unit-element_access2.cpp @@ -421,10 +421,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)")