Skip to content

add strict enum de/serialization macro - #4612

Closed
hnampally wants to merge 13 commits into
nlohmann:developfrom
hnampally:issue-3992
Closed

hnampally wants to merge 13 commits into
nlohmann:developfrom
hnampally:issue-3992

Conversation

@hnampally

@hnampally hnampally commented Jan 20, 2025 •

Copy link
Copy Markdown
Contributor

#3992

  • The changes are described in detail, both the what and why.
  • If applicable, an #3992 is referenced.
  • The Code coverage remained at 100%. A test case for every new line of code.
  • If applicable, the documentation is updated.
  • The source code is amalgamated by running make amalgamate.

Read the Contribution Guidelines for detailed information.

Signed-off-by: Harinath Nampally <harinath922@gmail.com>
@github-actions

Copy link
Copy Markdown

🔴 Amalgamation check failed! 🔴

The source code has not been amalgamated. @hnampally
Please read and follow the Contribution Guidelines.

@coveralls

coveralls commented Jan 20, 2025 •

Copy link
Copy Markdown

Coverage Status

coverage: 99.186%. remained the same
when pulling 6747555 on hnampally:issue-3992
into 606b634 on nlohmann:develop.

Signed-off-by: Harinath Nampally <harinath922@gmail.com>
Signed-off-by: Harinath Nampally <harinath922@gmail.com>
Signed-off-by: Harinath Nampally <harinath922@gmail.com>
Comment thread docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum _strict.md Outdated
Comment thread docs/mkdocs/docs/examples/nlohmann_json_deserialize_enum_strict.cpp Outdated
Comment thread docs/mkdocs/docs/examples/nlohmann_json_deserialize_enum_strict.cpp Outdated
Signed-off-by: Harinath Nampally <harinath922@gmail.com>
Signed-off-by: Harinath Nampally <harinath922@gmail.com>
Signed-off-by: Harinath Nampally <harinath922@gmail.com>
Comment thread include/nlohmann/detail/macro_scope.hpp Outdated
@github-actions

Copy link
Copy Markdown

🔴 Amalgamation check failed! 🔴

The source code has not been amalgamated. @hnampally
Please read and follow the Contribution Guidelines.

Signed-off-by: Harinath Nampally <harinath922@gmail.com>
Comment thread docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict.cpp Outdated
Comment thread docs/mkdocs/docs/features/enum_conversion.md Outdated
Comment thread include/nlohmann/detail/macro_scope.hpp Outdated
Signed-off-by: Harinath Nampally <harinath922@gmail.com>
Signed-off-by: Harinath Nampally <harinath922@gmail.com>
Comment thread include/nlohmann/detail/macro_scope.hpp Outdated
template<typename T>
[[noreturn]] inline void json_throw_from_serialize_macro(T&& exception)
{
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND) || defined(EXCEPTIONS)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When defining JSON_THROW in the same file, we use the following code to detect exceptions. Please use the same here to avoid issues.

#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh okay, thanks!

Comment thread include/nlohmann/detail/macro_scope.hpp Outdated
}); \
if (it == std::end(m)) { \
auto value = static_cast<typename std::underlying_type<ENUM_TYPE>::type>(e); \
nlohmann::detail::json_throw_from_serialize_macro(nlohmann::detail::type_error::create(302, nlohmann::detail::concat("can't serialize - enum value ", std::to_string(value), " out of range"), &j)); \

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the exception message. What about

serialization failed: enum value ... is out of range

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that sounds better, thanks!

Comment thread include/nlohmann/detail/macro_scope.hpp Outdated
return ej_pair.second == j; \
}); \
if (it == std::end(m)) \
nlohmann::detail::json_throw_from_serialize_macro(nlohmann::detail::type_error::create(302, nlohmann::detail::concat("can't deserialize - invalid json value : ", j.dump()), &j)); \

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above:

deserialization failed: invalid JSON value '...'

Signed-off-by: Harinath Nampally <harinath922@gmail.com>
Comment thread docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum _strict.md Outdated
Comment thread docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum _strict.md Outdated
Comment thread docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum _strict.md Outdated

- 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.
- If a JSON value appears more than once in the mapping, only the first occurrence will be used for deserialization,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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.

NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(Color, {
  { Red, "red" },
  { Green, nlohmann::json(1) },
  { Blue, nlohmann::json({{{"purple", "people eater"}}})}
})


int main()
{
  nlohmann::json j;
  j = { Red, Green, Blue };
  std::cout << j.dump() << "\n";
  auto j2 = nlohmann::json::parse(j.dump());
  std::vector<Color> vec = j2;
  std::cout << vec[0] << vec[1] << vec[2];
}
["red",1,[{"purple":"people eater"}]]
012

@hnampally Is this intended behavior, or did this just accidentally fall out of the second parameter being BasicJsonType instead of std::string?

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.

Signed-off-by: Harinath Nampally <harinath922@gmail.com>
Expected output:

```
[json.exception.type_error.302] serialization failed: enum value 3 is out of range

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also use an include here:

--8<-- "examples/nlohmann_json_serialize_enum_strict.output"

Expected output:

```
[json.exception.type_error.302] deserialization failed: invalid JSON value "yellow"

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also use an include here:

--8<-- "examples/nlohmann_json_deserialize_enum_strict.output"


int main()
{

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The 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

@gregmarr

Copy link
Copy Markdown
Contributor

It looks like you have a space in your filename here:
docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum _strict.md

Also, the discussion about strings vs arbitrary json for the value has been marked outdated because there was a change in the file. @nlohmann did you see that discussion?

Signed-off-by: Harinath Nampally <harinath922@gmail.com>
@hnampally
hnampally requested a review from nlohmann February 4, 2025 04:55
@jmonticelli

jmonticelli commented Apr 1, 2025 •

Copy link
Copy Markdown

This looks particularly useful, I was surprised by the behavior of the default enum serialization macro.
Thanks for putting this PR up btw @hnampally

@github-actions

Copy link
Copy Markdown

This pull request has been marked as stale because it has had no activity for 30 days. While we won’t close it automatically, we encourage you to update or comment if it is still relevant. Keeping pull requests active and up-to-date helps us review and merge changes more efficiently. Thank you for your contributions!

@github-actions github-actions Bot added the state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated label May 11, 2026
@nlohmann

Copy link
Copy Markdown
Owner

@hnampally I know it's been a while, but would you be willing to pick this up again?

@hnampally

Copy link
Copy Markdown
Contributor Author

@hnampally I know it's been a while, but would you be willing to pick this up again?

@nlohmann Sure, let me give this PR a quick re-read and hopefully we can get it merged/closed.

@github-actions github-actions Bot removed the state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated label May 18, 2026
@gregmarr

Copy link
Copy Markdown
Contributor

@nlohmann Isn't this the same thing as #5151 which is just about ready to go?

@hnampally hnampally closed this May 18, 2026
@hnampally

Copy link
Copy Markdown
Contributor Author

#5151 solves the same issue and ready to go, therefore cloing this PR

@nlohmann

Copy link
Copy Markdown
Owner

@hnampally Sorry for the confusion!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants