diff --git a/doc/ref/corelib/basic_json.md b/doc/ref/corelib/basic_json.md index 8ab66e4976..c72108bed2 100644 --- a/doc/ref/corelib/basic_json.md +++ b/doc/ref/corelib/basic_json.md @@ -206,6 +206,10 @@ for their storage, otherwise attempts to return a default constructed allocator. at
at_or_null
Return the specified value. + + at
at_or_null
+ Attempts to convert a basic_json value to a value of a type if it matches, otherwise a default value. + get_value_or Return the specified value if available, otherwise a default value. diff --git a/doc/ref/corelib/json/as.md b/doc/ref/corelib/json/as.md index 13b7034868..25ec0494a2 100644 --- a/doc/ref/corelib/json/as.md +++ b/doc/ref/corelib/json/as.md @@ -55,7 +55,7 @@ Output: (1) 2147483647 (2) -2147483648 (3) 2147483648 -(4) ÷ +(4) � (5) 4294967286 (6) 10 (7) 10.5 diff --git a/doc/ref/corelib/json/as_or.md b/doc/ref/corelib/json/as_or.md new file mode 100644 index 0000000000..0c2079fb15 --- /dev/null +++ b/doc/ref/corelib/json/as_or.md @@ -0,0 +1,55 @@ +### jsoncons::basic_json::as_or + +```cpp +template +T as_or(U&& default_value) const; +``` + +Checks the value of the json value with the template value using [json_type_traits](../json_type_traits.md), and converts if it matches, or returns a default value if it doesn't. + +See [as](as.md) for details on the value returned. + +### Type requirements + +- `U` must be convertible to `T` + +### Examples + +#### Return a value if the type matches, or a default value otherwise + +```cpp +#include + +int main() +{ + json j = json::parse("\"Hello World\""); + + std::cout << j.as_or(-1) << "\n"; + std::cout << j.as_or("null") << "\n"; +} +``` +Output: +``` +-1 +Hello World +``` + +#### Return a value if it exists and the type matches, or a default value otherwise + +```cpp +#include + +int main() +{ + json j(json_object_arg, {{"author","Evelyn Waugh"},{"title","Sword of Honour"},{"id","0"}}); + std::cout << j.at_or_null("author").as_or("unknown") << "\n"; + std::cout << j.at_or_null("category").as_or("fiction") << "\n"; + std::cout << j.at_or_null("id").as_or(-1) << "\n"; +} +``` +Output: +``` +Evelyn Waugh +fiction +-1 +``` diff --git a/doc/ref/corelib/json/get_value_or.md b/doc/ref/corelib/json/get_value_or.md index bc07b86187..b6cfa583df 100644 --- a/doc/ref/corelib/json/get_value_or.md +++ b/doc/ref/corelib/json/get_value_or.md @@ -1,7 +1,7 @@ ### jsoncons::basic_json::get_value_or ```cpp -template +template T get_value_or(const string_view_type& name, U&& default_value) const; ``` diff --git a/include/jsoncons/basic_json.hpp b/include/jsoncons/basic_json.hpp index ff271dc2f9..e6c7ec1b18 100644 --- a/include/jsoncons/basic_json.hpp +++ b/include/jsoncons/basic_json.hpp @@ -3699,6 +3699,24 @@ namespace jsoncons { } } + template + typename std::enable_if::value,T>::type + as_or(U&& default_value) const + { + static_assert(std::is_convertible::value, + "as_or: U must be convertible to T"); + using T_type_traits = json_type_traits; + if (T_type_traits::is(*this)) + { + T val = T_type_traits::as(*this); + return val; + } + else + { + return static_cast(std::forward(default_value)); + } + } + const basic_json& at_or_null(const string_view_type& key) const { switch (storage_kind()) diff --git a/test/corelib/src/json_object_tests.cpp b/test/corelib/src/json_object_tests.cpp index 0dbf70981e..5838b55fa6 100644 --- a/test/corelib/src/json_object_tests.cpp +++ b/test/corelib/src/json_object_tests.cpp @@ -297,6 +297,40 @@ TEST_CASE("test_empty_object_move_assignment") CHECK(c.is_object()); } +TEST_CASE("as_or test") +{ + json a = json::parse(R"( + { + "key1" : "value1", + "key2" : "3.7", + "key3" : 1.5, + "key4" : 1 + } + )"); + + std::string s1 = a.as_or("null"); + std::string s2 = a["key1"].as_or("null"); + std::string s3 = a["key2"].as_or("null"); + std::string s4 = a["key3"].as_or("null"); + int i1 = a["key1"].as_or(-1); + int i2 = a["key3"].as_or(-1); + int i3 = a["key4"].as_or(-1); + double d1 = a["key2"].as_or(-1.0); + double d2 = a["key3"].as_or(-1.0); + double d3 = a["key4"].as_or(-1.0); + + CHECK(s1 == std::string("null")); + CHECK(s2 == std::string("value1")); + CHECK(s3 == std::string("3.7")); + CHECK(s4 == std::string("null")); + CHECK(i1 == -1); + CHECK(i2 == -1); + CHECK(i3 == 1); + CHECK(d1 == -1.0); + CHECK(d2 == 1.5); + CHECK(d3 == -1.0); +} + TEST_CASE("at_or_null test") { json a = json::parse(R"(