From ae8f9cf54c4e361ff6005a6703d3fb3680c02f73 Mon Sep 17 00:00:00 2001 From: supsm Date: Sat, 8 Feb 2025 23:19:39 -0800 Subject: [PATCH 1/2] add basic_json::as_or and tests --- include/jsoncons/basic_json.hpp | 18 ++++++++++++++ test/corelib/src/json_object_tests.cpp | 34 ++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/include/jsoncons/basic_json.hpp b/include/jsoncons/basic_json.hpp index ff271dc2f..e6c7ec1b1 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 0dbf70981..5838b55fa 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"( From 973f8c30efbb50ea3e76a30bc4b5f977b3c23551 Mon Sep 17 00:00:00 2001 From: supsm Date: Sat, 8 Feb 2025 23:21:11 -0800 Subject: [PATCH 2/2] add documentation for as_or --- doc/ref/corelib/basic_json.md | 4 ++ doc/ref/corelib/json/as.md | 2 +- doc/ref/corelib/json/as_or.md | 55 ++++++++++++++++++++++++++++ doc/ref/corelib/json/get_value_or.md | 2 +- 4 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 doc/ref/corelib/json/as_or.md diff --git a/doc/ref/corelib/basic_json.md b/doc/ref/corelib/basic_json.md index 8ab66e497..c72108bed 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 13b703486..25ec0494a 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 000000000..0c2079fb1 --- /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 bc07b8618..b6cfa583d 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; ```