Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

JSON as_or accessor #591

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/ref/corelib/basic_json.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ for their storage, otherwise attempts to return a default constructed allocator.
<td><a href="json/at.md">at<br>at_or_null</a></td>
<td>Return the specified value.</td>
</tr>
<tr>
<td><a href="json/as_or.md">at<br>at_or_null</a></td>
<td>Attempts to convert a basic_json value to a value of a type if it matches, otherwise a default value.</td>
</tr>
<tr>
<td><a href="json/get_value_or.md">get_value_or</a></td>
<td>Return the specified value if available, otherwise a default value.</td>
Expand Down
2 changes: 1 addition & 1 deletion doc/ref/corelib/json/as.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Output:
(1) 2147483647
(2) -2147483648
(3) 2147483648
(4) ÷
(4) �
(5) 4294967286
(6) 10
(7) 10.5
Expand Down
55 changes: 55 additions & 0 deletions doc/ref/corelib/json/as_or.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
### jsoncons::basic_json::as_or

```cpp
template <typename T,typename U>
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 <jsoncons/json.hpp>

int main()
{
json j = json::parse("\"Hello World\"");

std::cout << j.as_or<int>(-1) << "\n";
std::cout << j.as_or<std::string>("null") << "\n";
}
```
Output:
```
-1
Hello World
```

#### Return a value if it exists and the type matches, or a default value otherwise

```cpp
#include <jsoncons/json.hpp>

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<std::string>("unknown") << "\n";
std::cout << j.at_or_null("category").as_or<std::string>("fiction") << "\n";
std::cout << j.at_or_null("id").as_or<int>(-1) << "\n";
}
```
Output:
```
Evelyn Waugh
fiction
-1
```
2 changes: 1 addition & 1 deletion doc/ref/corelib/json/get_value_or.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
### jsoncons::basic_json::get_value_or

```cpp
template <typename T,class U>
template <typename T,typename U>
T get_value_or(const string_view_type& name, U&& default_value) const;
```

Expand Down
18 changes: 18 additions & 0 deletions include/jsoncons/basic_json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3699,6 +3699,24 @@ namespace jsoncons {
}
}

template <typename T,typename U>
typename std::enable_if<is_json_type_traits_specialized<basic_json,T>::value,T>::type
as_or(U&& default_value) const
{
static_assert(std::is_convertible<U&&, T>::value,
"as_or: U must be convertible to T");
using T_type_traits = json_type_traits<basic_json,T>;
if (T_type_traits::is(*this))
{
T val = T_type_traits::as(*this);
return val;
}
else
{
return static_cast<T>(std::forward<U>(default_value));
}
}

const basic_json& at_or_null(const string_view_type& key) const
{
switch (storage_kind())
Expand Down
34 changes: 34 additions & 0 deletions test/corelib/src/json_object_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string>("null");
std::string s2 = a["key1"].as_or<std::string>("null");
std::string s3 = a["key2"].as_or<std::string>("null");
std::string s4 = a["key3"].as_or<std::string>("null");
int i1 = a["key1"].as_or<int>(-1);
int i2 = a["key3"].as_or<int>(-1);
int i3 = a["key4"].as_or<int>(-1);
double d1 = a["key2"].as_or<double>(-1.0);
double d2 = a["key3"].as_or<double>(-1.0);
double d3 = a["key4"].as_or<double>(-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"(
Expand Down
Loading