Skip to content

Commit

Permalink
implemented a proposal for #278
Browse files Browse the repository at this point in the history
  • Loading branch information
nlohmann committed Jul 31, 2016
1 parent 4444ef9 commit 6bedee7
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 0 deletions.
31 changes: 31 additions & 0 deletions src/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3854,6 +3854,37 @@ class basic_json
return value(ptr, string_t(default_value));
}

template <class ValueType, typename
std::enable_if<
std::is_convertible<basic_json_t, ValueType>::value
, int>::type = 0>
ValueType value_with_type(const typename object_t::key_type& key,
ValueType default_value) const
{
// derive JSON value type from given default value
const value_t return_value_type = basic_json(default_value).type();

// at only works for objects
if (is_object())
{
// if key is found and stored value has the same type as the
// default value, return value and given default value otherwise
const auto it = find(key);
if (it != end() and it->type() == return_value_type)
{
return *it;
}
else
{
return default_value;
}
}
else
{
throw std::domain_error("cannot use value() with " + type_name());
}
}

/*!
@brief access the first element
Expand Down
31 changes: 31 additions & 0 deletions src/json.hpp.re2c
Original file line number Diff line number Diff line change
Expand Up @@ -3854,6 +3854,37 @@ class basic_json
return value(ptr, string_t(default_value));
}

template <class ValueType, typename
std::enable_if<
std::is_convertible<basic_json_t, ValueType>::value
, int>::type = 0>
ValueType value_with_type(const typename object_t::key_type& key,
ValueType default_value) const
{
// derive JSON value type from given default value
const value_t return_value_type = basic_json(default_value).type();

// at only works for objects
if (is_object())
{
// if key is found and stored value has the same type as the
// default value, return value and given default value otherwise
const auto it = find(key);
if (it != end() and it->type() == return_value_type)
{
return *it;
}
else
{
return default_value;
}
}
else
{
throw std::domain_error("cannot use value() with " + type_name());
}
}

/*!
@brief access the first element

Expand Down
24 changes: 24 additions & 0 deletions test/src/unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14373,6 +14373,30 @@ TEST_CASE("regression tests")

CHECK(at_integer == val_integer);
}

SECTION("issue #278 - Do not throw exception when default_value's type does not match the actual type")
{
json j =
{
{"port", 1234}, {"proxy", true}
};

int port1 = j.value_with_type("port", 8080);
int port2 = j.value_with_type("the_port", 8080);
int port3 = j.value_with_type("proxy", 8080);

bool proxy1 = j.value_with_type("proxy", false);
bool proxy2 = j.value_with_type("the_proxy", false);
bool proxy3 = j.value_with_type("port", false);

CHECK(port1 == 1234);
CHECK(port2 == 8080);
CHECK(port3 == 8080);

CHECK(proxy1 == true);
CHECK(proxy2 == false);
CHECK(proxy3 == false);
}
}

// special test case to check if memory is leaked if constructor throws
Expand Down

0 comments on commit 6bedee7

Please sign in to comment.