You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[C++17] Allow std::optional to convert to nlohmann::json #1749
This is what I assume to be a fairly minor change to the library's logic, but would represent a large improvement in usability.
Feature request
C++17 adds std::optional<T>. Let std::optional<T> convert to nlohmann::json.
If std::optional<T> is empty, I would expect this to result in null - if std::optional<T>, I would expect it to result in the contained value converted.
Use case example
The change would simplify (especially nested) uses of std::optional.
For example, imagine a simple key-value map, where each integer key can optionally have a localized string representation for each of 8 locales. The client dynamically selects the "best" available locale depending on user preferences.
In server code, one could express this as a std::vector<std::array<std::optional<std::string>, 8>>.
Currently, this type does not convert to nlohmann::json because std::optional<std::string> does not - resulting in needing to allocate a bunch of temporaries so the inner conversions can be done "manually".
Allowing std::optional to convert to nlohmann::json would simplify this logic greatly.
Reacted by fz-qs, Jonas Otto, Amr, Robert Hensing, Jonathan Edelman, Gustov Vladimir, THE-FYP, Aleksander Østrup, ErvinXie, Matheus Gabriel Werny and 4 more
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, I believe the library would benefit from the ability to return a std::optional from a getter method -- this way, client programs could avoid having to catch exceptions to detect a missing value, etc.:
std::string name = j["name"].get_optional<std::string>().value_or("default-name");
Qt uses something similar in their config file interface. This makes it very easy to save a default json file on a load failure -- you deserialize a class from json with default values using std::optional and then serialize the resulting class back to json; if there were no changes to the class, the json should be identical, otherwise missing data will be added to the output json.
It's often useful to differentiate about not getting the value, and getting some default value. Also, perhaps the item is there but it's not of the expected type.
I'm dealing with such cases all the time, and using something like:
I looked at AppVeyor and noticed that the builds fail only when the latest language standard is being used in Visual Studio. Essentially the builds fail when std::optional should be available.
I checked out your branch, tested on local Visual Studio 2017 and found out the issue. The preprocessor definition JSON_HAS_CPP_17 is being used too early before the language standard detection is done. The "error C2039: 'optional': is not a member of 'std'" is caused by the later code in compilation using std::optional while the #include statement is skipped because JSON_HAS_CPP_17 has not been defined yet.
However, now there is another error in unit-conversions.cpp lines 1624 and 1633 where there is no suitable conversion from nlohmann::json to std::vector containing std::optional (1624) or std::map containing std::optional (1633). I am not familiar with the code base so I am unsure where exactly the conversion should happen.
Thank you! Will this change be incorporated into nlohmann-json? As a new user, this is the behavior I expected from NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE (after defining to/from_json for optional, as described in the readme).
(My template-fu is very weak, so I had to use overloading to implement the different logic for std::optionals. Not sure if this is always correct. Worked for me so far.)
In NixOS/nix@3180c09/src/libutil/json-utils.hh#L43-L124 I made a little trait class to avoid issues where null being used in the underlying serialization would break round-trip parsing. Do we have anything like that in the merged PR? Should we have anything like that?
I think so - especially before the current develop version is actually released and a later change would be a breaking change.
This is not really a function of to_json for std::optional<T>. It's either for json.dump, meaning don't write out null values, or to_json for Properties, meaning don't put an entry in the json object for the optional if it's not engaged.
Activity
jaredgrubb commentedon Sep 13, 2019
It's a neat idea, though this library is still intended as a C++11 library. I wonder at what point that could change to allow things like this?
nlohmann commentedon Sep 16, 2019
The library defines a macro
JSON_HAS_CPP_17to detect C++17. With that, the feature could be realized. The required code should look similar to #760.stale commentedon Oct 16, 2019
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.
jnhyatt commentedon Oct 20, 2019
In addition, I believe the library would benefit from the ability to return a
std::optionalfrom a getter method -- this way, client programs could avoid having to catch exceptions to detect a missing value, etc.:Qt uses something similar in their config file interface. This makes it very easy to save a default json file on a load failure -- you deserialize a class from json with default values using
std::optionaland then serialize the resulting class back to json; if there were no changes to the class, the json should be identical, otherwise missing data will be added to the output json.nlohmann commentedon Oct 23, 2019
Wouldn't this be similar to
j.value("name", "default-name")?jnhyatt commentedon Oct 23, 2019
Yes, it would be very similar in most cases. I admit I hadn't searched the library exhaustively for such a feature before having made this suggestion.
djcb commentedon Nov 20, 2019
It's often useful to differentiate about not getting the value, and getting some default value. Also, perhaps the item is there but it's not of the expected type.
I'm dealing with such cases all the time, and using something like:
Without it, I need to add type-checks and/or try/catch blocks everywhere, which isn't very nice.
nlohmann commentedon Nov 23, 2019
I started working on this in a feature branch https://github.com/nlohmann/json/tree/feature/optional. Unfortunately, I currently cannot make the code compile with MSVC: https://ci.appveyor.com/project/nlohmann/json/builds/29069989
Any ideas?
remedi commentedon Dec 17, 2019
I looked at AppVeyor and noticed that the builds fail only when the latest language standard is being used in Visual Studio. Essentially the builds fail when std::optional should be available.
I checked out your branch, tested on local Visual Studio 2017 and found out the issue. The preprocessor definition JSON_HAS_CPP_17 is being used too early before the language standard detection is done. The "error C2039: 'optional': is not a member of 'std'" is caused by the later code in compilation using std::optional while the #include statement is skipped because JSON_HAS_CPP_17 has not been defined yet.
However, now there is another error in unit-conversions.cpp lines 1624 and 1633 where there is no suitable conversion from nlohmann::json to std::vector containing std::optional (1624) or std::map containing std::optional (1633). I am not familiar with the code base so I am unsure where exactly the conversion should happen.
27 remaining items
vid512 commentedon Aug 30, 2024
Thank you! Will this change be incorporated into nlohmann-json? As a new user, this is the behavior I expected from NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE (after defining to/from_json for optional, as described in the readme).
vid512 commentedon Sep 7, 2024
I also would change to_json, to not write optional values if they are nullopt.
(My template-fu is very weak, so I had to use overloading to implement the different logic for std::optionals. Not sure if this is always correct. Worked for me so far.)
Example of concrete use case where this behavior is useful: Many optional values in https://microsoft.github.io/debug-adapter-protocol//specification.html
Xtreme-G commentedon Oct 22, 2024
I would like to enable this behavior as well, could you please clarify how and where you added this?
Ericson2314 commentedon Nov 25, 2024
In https://github.com/NixOS/nix/blob/3180c09723c3b61d682732c308c74e2087ac628f/src/libutil/json-utils.hh#L43-L124 I made a little trait class to avoid issues where
nullbeing used in the underlying serialization would break round-trip parsing. Do we have anything like that in the merged PR? Should we have anything like that?nlohmann commentedon Nov 25, 2024
I think so - especially before the current develop version is actually released and a later change would be a breaking change.
[Ref] mpt/json/json.hpp: Prepare for official std::optional support. …
lingxd commentedon Oct 27, 2025
to_json -> null
from_json -> std::nullopt
I want to_json not to serialize null.
example:
i want
{ "controlType": "NormalLoad", "timestamp": 1761566190 }In fact
{ "controlType": "NormalLoad", "executionTime" : null, "timestamp": 1761566190 }gregmarr commentedon Oct 27, 2025
This is not really a function of
to_jsonforstd::optional<T>. It's either forjson.dump, meaning don't write outnullvalues, orto_jsonforProperties, meaning don't put an entry in thejsonobject for the optional if it's not engaged.