json
json copied to clipboard
Introduce try_get() and try_deserialize()
I propose new method json.try_get<MyType>()
, which works similar to json.get<MyType>()
. It can be extended by providing adl_serializer<MyType>::try_deserialize()
function. Unlike get
method, the return type of try_get
is assumed to have a different return type to MyType
and can be std::optional
, tl::expected
or other wrapper
Why is it needed?
- Users may prefer to handle errors without exceptions for the sake of performance
- Or, some users like more functional program structuring, for example, using monads, this allows not only to handle errors, but also to return some additional info about deserialization, such as warnings or even detailed debug logs.
- Maybe something else?
Why not just allow json.get<MyType>()
to return any type, different from MyType
?
- This is not obvious code behavior and some users may not expect a different return type
- Some users may want to explicitly distinguish between
json.get<MyType>()
andjson.try_get<MyType>()
, or even have both
What about json.get<MyMonad<MyType>>()
? Why not?
- Users can define their own version of
try_get()
with custom return type once and don't bother about return type anymore every timeget()
is called. This is quite important in a large codebase whereget()
calls many times for same type - Or, even more importantly, I think
json.try_get<MyType>()
is easier to read and is a good abstraction compared tojson.get<MyMonad<MyType>>()
- Also, I think
json.try_get<T>()
is the better way to return optional thanjson.get<std::optional<T>>()
from #2229
So, is noexcept our goal? Does json.try_get<X>()
throw exceptions?
- It's depend on user implementation of
try_deserialize()
and it is the responsibility of the users to marktry_deserialize()
asnoexcept(true)
ornoexcept(false)
.
Should we implement try_deserialize()
for basic types?
- I'm not sure.
tl::expected
orstd::optional
could be suitable for this, but most likely, the user will want to write their own monadic type or wrapper. Also, there may be a problem when users include two libraries that use nlohman_json and specializing differentadl_serializer
for the same basic type. Maybe we can implementtry_deserialize
lookup through tag dispatching with adl and allow additional arguments to be passed totry_get()
, then users can create their own unambiguous overloads. More research is needed here and right now I think the answer is no
About naming
- I'm not sure about the naming. I think,
try_deserialize()
is too contrast tofrom_json()
, but I don't know what name is better
Coverage remained the same at 100.0% when pulling 7f4d035cfe468f05efdb548f3995bbba71c20250 on oficsu:try_deserialize_squash into 43ab8a2357de50279efec307b718d25c44176e98 on nlohmann:develop.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
After thinking about this PR again, I decided that it requires some more work. Perhaps design could be better. I don't have much free time at the moment, so I'll come back later and think about this PR again. Do I need to close PR for this time or can I leave PR as a draft?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
In addition, it would be handy to have the macros such as: NLOHMANN_DEFINE_TYPE_INTRUSIVE use a version which is ok if the data isn't found. try/catching everything can be expensive if "not found" is an acceptable state.
Expanding even further to the "optional is ok", bool from_json(.......) whereby validation can be reported as a warning, or diagnostic, but not as an error that is try/catch.
It means, NLOHMANN_DEFINE_TYPE_INTRUSIVE isn't as useful, or jsons become bigger with required params being null instead of leaving them out.
An example additional macro: NLOHMANN_DEFINE_TYPE_TRY_INTRUSIVE(.....) In this simple macro naming, it's "all or none", and that's ok as optional might be the common usecase.
Additionally, having from_json (and thus, macro) return true/false, or count of missing params, or a tuple of found / maxcount would be helpful and allow for custom detection.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Would it make sense extending this to have an optional default value?
I am in the process of porting over a project from jsoncpp to nlohmann-json, and the former has this as a very convenient feature (for us at least), i.e. .get("field", Json::object())
to get an optional empty object if not present.
Is there a best practice for this in the current library?
Would it make sense extending this to have an optional default value?
I am in the process of porting over a project from jsoncpp to nlohmann-json, and the former has this as a very convenient feature (for us at least), i.e.
.get("field", Json::object())
to get an optional empty object if not present.Is there a best practice for this in the current library?
The value
function should do this: https://json.nlohmann.me/api/basic_json/value/.
@nlohmann oh wow, that certainly looks like it, thank you!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
After thinking about this PR again, I decided that it requires some more work. Perhaps design could be better. I don't have much free time at the moment, so I'll come back later and think about this PR again. Do I need to close PR for this time or can I leave PR as a draft?
@oficsu Any progress here?
@gregmarr, no, I couldn't come up with a better design