json: Do not throw exception when default_value's type does not match the actual type
Thanks for this great library. I have been quite happy about almost every aspect of the library, except one point about the value
method on object.
Consider this sample code.
int main() {
nlohmann::json j = { {"b", nullptr}};
std::string result = j.value("b", "1"); // std::domain_error: type must be string, but is null
return 0;
}
When I’m using value
to specify a default value of a key, I pretty much don’t care about whether it exists or not, whether it is a valid value or not. It’s pretty much like, if it failed to fetch a value of a specific type, then return the default_value I specified.
So I’m thinking about changing the following method: https://github.com/nlohmann/json/blob/develop/src/json.hpp#L3653
to something like this:
template <class ValueType, typename
std::enable_if<
std::is_convertible<basic_json_t, ValueType>::value
, int>::type = 0>
ValueType value(const typename object_t::key_type& key, ValueType default_value) const
{
// at only works for objects
if (is_object())
{
// if key is found, return value and given default value otherwise
const auto it = find(key);
if (it != end())
{
try
{
return *it;
}
catch (...)
{
// if some kind of exception occurred, return default value
return default_value;
}
}
else
{
return default_value;
}
}
else
{
throw std::domain_error("cannot use value() with " + type_name());
}
}
Which I think will make the value
method a lot easier to use. What do you think? @nlohmann
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 3
- Comments: 48 (25 by maintainers)
Commits related to this issue
- implemented a proposal for #278 — committed to nlohmann/json by nlohmann 8 years ago
This bugs me as well, I would like to see much more permissives functions to avoid code like this:
I would like to see much more permissives implicit conversions functions that also allow casting to default values if not.
This will help us deserialize untrusted input much easier! Like this:
What do you think?
It is very nice.
@jackb-p a behaviour change in a public function is considered as breaking change and thus should require a major version upgrade (if following semantic versioning).
For me there is no problem if it is a new function, it’s much more explicit.
I implemented the proposal of @markand with a slight change: instead of having the user provide a type, the type is derived from the default value. There are two cases:
An exception is only thrown if the function is called on a JSON value which is not an object.
There are still some issues with respect to number types: currently,
-100
and100
would be treated as different types. This may yield situations in which the return value is returned even if there is a stored value which just happens to be of the wrong number type…The function (ignore the name for now) looks like this:
Here are some test cases:
What do you think?
value
function?We could have a nothrow version For example in java json.getString(key) <- throw version json.optString(key, fallback value) <- nothrow version
what about having a nothrow version of
value
so that users can choose which to use?What about only if the value is null? To me it makes sense for .value to return the default value if the value is null. For my usage, there is an API that returns JSON, but a certain string is set to null instead of not being present if it is not relevant, and I want to use the default value for this.