implemented a proposal for #278
diff --git a/src/json.hpp b/src/json.hpp
index 878fb89..3ad68d0 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -3854,6 +3854,37 @@
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
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 32482ea..367c0ee 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -3854,6 +3854,37 @@
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
diff --git a/test/src/unit.cpp b/test/src/unit.cpp
index 79a4bb0..27aff7f 100644
--- a/test/src/unit.cpp
+++ b/test/src/unit.cpp
@@ -14373,6 +14373,30 @@
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