diff --git a/include/nlohmann/json_view.hpp b/include/nlohmann/json_view.hpp index 3980b3ecd..13c9db53a 100644 --- a/include/nlohmann/json_view.hpp +++ b/include/nlohmann/json_view.hpp @@ -392,7 +392,13 @@ class basic_json_view string_t value(string_view_t key, const char* default_value) const { - return value(key, string_t(default_value)); + if (NLOHMANN_VIEW_UNLIKELY(!is_object())) + { + detail::view::throw_type_error(306, "cannot use value() with ", type_name()); + } + // (the default is made only if there is no such member) + const basic_json_view r = lookup(key); + return r.is_discarded() ? string_t(default_value) : r.template get(); } /// the value a JSON pointer refers to converted to T, or the default @@ -411,7 +417,12 @@ class basic_json_view string_t value(const json_pointer& ptr, const char* default_value) const { - return value(ptr, string_t(default_value)); + if (NLOHMANN_VIEW_UNLIKELY(!is_structured())) + { + detail::view::throw_type_error(306, "cannot use value() with ", type_name()); + } + const basic_json_view r = detail::view::resolve_pointer(*this, detail::json_pointer_access::reference_tokens(ptr), detail::view::pointer_mode::value); + return r.is_discarded() ? string_t(default_value) : r.template get(); } /// the first element or member value; a primitive value itself. Throws diff --git a/single_include/nlohmann/json_view.hpp b/single_include/nlohmann/json_view.hpp index 0b2365a00..5e055fd7b 100644 --- a/single_include/nlohmann/json_view.hpp +++ b/single_include/nlohmann/json_view.hpp @@ -7731,7 +7731,13 @@ class basic_json_view string_t value(string_view_t key, const char* default_value) const { - return value(key, string_t(default_value)); + if (NLOHMANN_VIEW_UNLIKELY(!is_object())) + { + detail::view::throw_type_error(306, "cannot use value() with ", type_name()); + } + // (the default is made only if there is no such member) + const basic_json_view r = lookup(key); + return r.is_discarded() ? string_t(default_value) : r.template get(); } /// the value a JSON pointer refers to converted to T, or the default @@ -7750,7 +7756,12 @@ class basic_json_view string_t value(const json_pointer& ptr, const char* default_value) const { - return value(ptr, string_t(default_value)); + if (NLOHMANN_VIEW_UNLIKELY(!is_structured())) + { + detail::view::throw_type_error(306, "cannot use value() with ", type_name()); + } + const basic_json_view r = detail::view::resolve_pointer(*this, detail::json_pointer_access::reference_tokens(ptr), detail::view::pointer_mode::value); + return r.is_discarded() ? string_t(default_value) : r.template get(); } /// the first element or member value; a primitive value itself. Throws diff --git a/tests/src/unit-json_view.cpp b/tests/src/unit-json_view.cpp index c873e3f55..670eb3465 100644 --- a/tests/src/unit-json_view.cpp +++ b/tests/src/unit-json_view.cpp @@ -1473,7 +1473,17 @@ TEST_CASE("json_view values") CHECK(exception_of([&] { static_cast(v.value("s", 0)); }) == without_path(exception_of([&] { static_cast(j.value("s", 0)); }))); CHECK(exception_of([&] { static_cast(v["n"].value("x", 0)); }) == without_path(exception_of([&] { static_cast(j["n"].value("x", 0)); }))); CHECK(exception_of([&] { static_cast(v["n"].value(json::json_pointer("/x"), 0)); }) == without_path(exception_of([&] { static_cast(j["n"].value(json::json_pointer("/x"), 0)); }))); + // string defaults: the member is not a string, or the value is neither an object nor an array + CHECK(exception_of([&] { static_cast(v.value("n", "default")); }) == without_path(exception_of([&] { static_cast(j.value("n", "default")); }))); + CHECK(exception_of([&] { static_cast(v["n"].value("x", "default")); }) == without_path(exception_of([&] { static_cast(j["n"].value("x", "default")); }))); + CHECK(exception_of([&] { static_cast(v.value(json::json_pointer("/n"), "default")); }) == without_path(exception_of([&] { static_cast(j.value(json::json_pointer("/n"), "default")); }))); + CHECK(exception_of([&] { static_cast(v["s"].value(json::json_pointer("/x"), "default")); }) == without_path(exception_of([&] { static_cast(j["s"].value(json::json_pointer("/x"), "default")); }))); #endif + // (defaults and members longer than the short string optimization) + CHECK(v.value("s", "a default longer than fifteen characters") == "text"); + CHECK(v.value("missing", "a default longer than fifteen characters") == "a default longer than fifteen characters"); + CHECK(v.value(json::json_pointer("/s"), "a default longer than fifteen characters") == "text"); + CHECK(v.value(json::json_pointer("/zz"), "a default longer than fifteen characters") == "a default longer than fifteen characters"); } }