-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add strict enum de/serialization macro #4612
base: develop
Are you sure you want to change the base?
Changes from 11 commits
06b667c
4ebebad
0083937
c6d9ea0
4444985
e7c021f
32cbaee
2898659
11165ef
0cda972
e25fc04
5f7d41c
6747555
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
# NLOHMANN_JSON_SERIALIZE_ENUM_STRICT | ||
|
||
```cpp | ||
#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(type, conversion...) | ||
``` | ||
|
||
The `NLOHMANN_JSON_SERIALIZE_ENUM_STRICT` allows to define a user-defined serialization for every enumerator. | ||
|
||
This macro declares strict serialization and deserialization functions (`to_json` and `from_json`) for an enum type. | ||
Unlike [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md), this macro enforces strict validation and | ||
throws errors for unmapped values instead of defaulting to the first enum value. | ||
|
||
## Parameters | ||
|
||
`type` (in) | ||
: name of the enum to serialize/deserialize | ||
|
||
`conversion` (in) | ||
: a pair of an enumerator and a JSON serialization; arbitrary pairs can be given as a comma-separated list | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would say "pairs" rather than "a pair", and "a JSON serialization" is odd, maybe "the string to be used in the JSON serialization. The "arbitrary pairs can be given as a comma-separated list" sounds weird to me.
|
||
|
||
## Default definition | ||
|
||
The macro adds two functions to the namespace which take care of the serialization and deserialization: | ||
|
||
```cpp | ||
template<typename BasicJsonType> | ||
inline void to_json(BasicJsonType& j, const type& e); | ||
template<typename BasicJsonType> | ||
inline void from_json(const BasicJsonType& j, type& e); | ||
``` | ||
|
||
## Notes | ||
|
||
!!! info "Prerequisites" | ||
|
||
The macro must be used inside the namespace of the enum. | ||
|
||
!!! important "Important notes" | ||
|
||
- If an enum value appears more than once in the mapping, only the first occurrence will be used for serialization, | ||
subsequent mappings for the same enum value will be ignored. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be worth putting in something here like "will currently be ignored but may result in an error in the future"? |
||
- If a JSON value appears more than once in the mapping, only the first occurrence will be used for deserialization, | ||
nlohmann marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "If a string value" since it's not an arbitrary json value but a string.... Oh, OH, it doesn't require that it be a string, does it? 😮 There's nothing in the code that requires that this be a string.
@hnampally Is this intended behavior, or did this just accidentally fall out of the second parameter being If this is intended behavior, it should definitely be documented before someone trips upon it accidentally, or someone relies on it and then someone else "fixes" it. If it's not intended behavior, then it should be fixed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
subsequent mappings for the same JSON value will be ignored. | ||
- Unlike `NLOHMANN_JSON_SERIALIZE_ENUM`, this macro enforces strict validation: | ||
- Attempting to serialize an unmapped enum value will throw a `type_error.302` exception | ||
- Attempting to deserialize an unmapped JSON value will throw a `type_error.302` exception | ||
- There is no default value behavior - all values must be explicitly mapped | ||
|
||
## Examples | ||
|
||
??? example "Example 1: Strict serialization" | ||
|
||
The example shows how `NLOHMANN_JSON_SERIALIZE_ENUM_STRICT` enforces strict validation when serializing an enum value that is not in the mapping: | ||
|
||
```cpp | ||
--8<-- "examples/nlohmann_json_serialize_enum_strict.cpp" | ||
``` | ||
|
||
Expected output: | ||
|
||
``` | ||
[json.exception.type_error.302] serialization failed: enum value 3 is out of range | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also use an include here:
|
||
``` | ||
|
||
??? example "Example 2: Strict deserialization" | ||
|
||
The example shows how `NLOHMANN_JSON_SERIALIZE_ENUM_STRICT` enforces strict validation when deserializing a JSON value that is not in the mapping: | ||
|
||
```cpp | ||
--8<-- "examples/nlohmann_json_deserialize_enum_strict.cpp" | ||
``` | ||
|
||
Expected output: | ||
|
||
``` | ||
[json.exception.type_error.302] deserialization failed: invalid JSON value "yellow" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also use an include here:
|
||
``` | ||
|
||
Both examples demonstrate: | ||
|
||
- Proper error handling using try-catch blocks | ||
- Clear error messages indicating the cause of failure | ||
- No default value behavior - all values must be explicitly mapped | ||
- Exception throwing for unmapped values | ||
|
||
## See also | ||
|
||
- [Specializing enum conversion](../../features/enum_conversion.md) | ||
- [`JSON_DISABLE_ENUM_SERIALIZATION`](json_disable_enum_serialization.md) | ||
|
||
## Version history | ||
|
||
- Added in version 3.11.4 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#include <iostream> | ||
#include <nlohmann/json.hpp> | ||
|
||
using json = nlohmann::json; | ||
|
||
namespace ns | ||
{ | ||
enum class Color | ||
{ | ||
red, green, blue | ||
}; | ||
|
||
NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(Color, | ||
{ | ||
{ Color::red, "red" }, | ||
{ Color::green, "green" }, | ||
{ Color::blue, "blue" }, | ||
}) | ||
} | ||
|
||
int main() | ||
{ | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove the empty line. Also: move line json j_yellow = "yellow"; above the comment // deserialization |
||
// deserialization | ||
json j_yellow = "yellow"; | ||
try | ||
{ | ||
auto yellow = j_yellow.template get<ns::Color>(); | ||
std::cout << j_yellow << " -> " << static_cast<int>(yellow) << std::endl; | ||
} | ||
catch (const nlohmann::json::exception& e) | ||
{ | ||
std::cout << e.what() << std::endl; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[json.exception.type_error.302] can't deserialize - invalid json value : "yellow" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#include <iostream> | ||
#include <nlohmann/json.hpp> | ||
|
||
using json = nlohmann::json; | ||
|
||
namespace ns | ||
{ | ||
enum class Color | ||
{ | ||
red, green, blue, pink | ||
}; | ||
|
||
NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(Color, | ||
{ | ||
{ Color::red, "red" }, | ||
{ Color::green, "green" }, | ||
{ Color::blue, "blue" }, | ||
}) | ||
} | ||
|
||
int main() | ||
{ | ||
// serialization | ||
try | ||
{ | ||
json j_red = ns::Color::pink; | ||
auto color = j_red.get<ns::Color>(); | ||
std::cout << static_cast<int>(color) << " -> " << j_red << std::endl; | ||
} | ||
catch (const nlohmann::json::exception& e) | ||
{ | ||
std::cout << e.what() << std::endl; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[json.exception.type_error.302] serialization failed: enum value 3 is out of range |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is missing some words.
I can see this is basically the same text as in the original, it should probably be updated there too.