Add NLOHMANN_JSON_SERIALIZE_ENUM_STRICT macro that throws type_error.302 on unknown JSON value (Fixes #3992)
Summary
This PR fixes #3992 by introducing a new macro
NLOHMANN_JSON_SERIALIZE_ENUM_STRICT, which throws a json.exception.type_error.302
when deserializing a JSON string that does not match any enumerator.
The existing NLOHMANN_JSON_SERIALIZE_ENUM macro remains unchanged to preserve backward compatibility.
Changes
- Added new macro
NLOHMANN_JSON_SERIALIZE_ENUM_STRICTinmacro_scope.hppthat throwstype_error.302for unmapped enum strings. - Added new test file
unit-serialize_enum_strict.cppvalidating the strict throwing behavior. - Regenerated single-header files using
make amalgamate. - Verified all tests using
ctest --output-on-failure.
Expected test impact
All existing tests for NLOHMANN_JSON_SERIALIZE_ENUM continue to pass unchanged.
New tests for NLOHMANN_JSON_SERIALIZE_ENUM_STRICT confirm that unknown JSON values now trigger exceptions.
Other unrelated floating-point mismatches (e.g., test-regression1_cpp11) are not affected by this change.
Documentation
A new documentation entry will be added at
docs/api/macros/nlohmann_json_serialize_enum_strict.md describing the stricter deserialization behavior.
Checklist
- [x] Implementation complete
- [x] New strict macro added (
NLOHMANN_JSON_SERIALIZE_ENUM_STRICT) - [x] New test added and passing
- [x] Single-header regenerated (
make amalgamate) - [x] Backward compatibility preserved
- [x] DCO signed
- [x] Documentation pending maintainer confirmation
i have made changes accordingly pls review
🔴 Amalgamation check failed! 🔴
The source code has not been amalgamated. @Ash-Jose Please read and follow the Contribution Guidelines.
coverage: 99.192% (+0.001%) from 99.191% when pulling 12319044db42395e8709fd58a04e79dad51fceb1 on Ash-Jose:fix/enum-deser-throw-on-unknown into 49026f799983840d7cf1a8109ffffe7eb4b1012c on nlohmann:develop.
🔴 Amalgamation check failed! 🔴
The source code has not been amalgamated. @Ash-Jose Please read and follow the Contribution Guidelines.
is this because of using concat amalgamation check seems to have passed this time around
is this because of using concat amalgamation check seems to have passed this time around
You need to include #include <nlohmann/detail/string_concat.hpp>.
included the header
🔴 Amalgamation check failed! 🔴
The source code has not been amalgamated. @Ash-Jose Please read and follow the Contribution Guidelines.
why are tests still failing??
Maybe some issue with the includes. Please try:
- remove the
string_concat.hppinclude - revert the code to using
std::string()... like you did before
Sorry for the confusion.
i have reverted it
should i redo in a different branch?? i dont understand why checks are failing
i dont understand why they still fail
Because there is more to forward-declare. I'm sorry, but it seems to be a more complicated issue to use an exception in the macro header.
The forward declarations aren't required for the macro definition, they're required where the things are used.
~I think the issue is that it's using the detail namespace. I don't think we do that for any of the other user space macros.~ Nope, simple type issue.
i have made changes accordingly this was the first version of my change although back then i wasnt able to make amalgamate work
its still failing a few tests is that concerning??
its still failing a few tests is that concerning??
Yes, one says you need to include <string> in macro_scope.hxx.
The fix for the other two is here: https://github.com/nlohmann/json/blob/af524ab666359f09a16bca1a41543a9a3a941251/tests/src/unit-unicode3.cpp#L23-L25
The "code scanning" one seems to be outside of the scope of your PR, since it's failing at
/home/runner/work/json/json/tests/src/unit-comparison.cpp:437:57: warning: ‘bool nlohmann::json_abi_ldvcmp_v3_12_0::basic_json<>::operator<=(const_reference) const is deprecated: Since 3.11.0; use undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON [-Wdeprecated-declarations]
437 | CHECK((j_values[i] <= j_values[j]) == !(j_values[j] < j_values[i]));
| ^
/home/runner/work/json/json/tests/thirdparty/doctest/doctest.h:2428:24: note: in definition of macro ‘DOCTEST_ASSERT_IMPLEMENT_1’
2428 | << __VA_ARGS__) DOCTEST_CLANG_SUPPRESS_WARNING_POP
| ^~~~~~~~~~~
/home/runner/work/json/json/tests/thirdparty/doctest/doctest.h:2970:20: note: in expansion of macro ‘DOCTEST_CHECK’
2970 | #define CHECK(...) DOCTEST_CHECK(__VA_ARGS__)
| ^~~~~~~~~~~~~
/home/runner/work/json/json/tests/src/unit-comparison.cpp:437:25: note: in expansion of macro ‘CHECK’
437 | CHECK((j_values[i] <= j_values[j]) == !(j_values[j] < j_values[i]));
| ^~~~~
In file included from /home/runner/work/json/json/tests/src/unit-comparison.cpp:19:
/home/runner/work/json/json/include/nlohmann/json.hpp:3775:10: note: declared here
3775 | bool operator<=(const_reference rhs) const noexcept
| ^~~~~~~~
🔴 Amalgamation check failed! 🔴
The source code has not been amalgamated. @Ash-Jose Please read and follow the Contribution Guidelines.
are these fails still related to my pr?
Yes, the CI is green on the base branch.
ignore this recent push, that was by accident
anyways, when i try to use JSON_THROW
i get error: 'JSON_THROW' was not declared in this scope; did you mean 'JSON_TRY'?
even though this exists
// allow disabling exceptions
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
#define JSON_THROW(exception) throw exception
#define JSON_TRY try
#define JSON_CATCH(exception) catch(exception)
#define JSON_INTERNAL_CATCH(exception) catch(exception)
#else
#include
Ugh, JSON_THROW is undefined by macro_unscope.hpp. @nlohmann Thoughts on letting that stay defined? Otherwise I guess there would need to be a helper function to do the actual JSON_THROW.
template <typename BasicJsonType>
inline void throw_enum_error(const BasicJsonType& j, const char* enum_type)
{
JSON_THROW(::nlohmann::detail::type_error::create(
302, std::string("invalid value for ") + enum_type + ": " + j.dump(), &j));
}
can i define a helper like this??
i have made the previously suggested changes like the positioning of string header and all but i am still waiting for reply on what to do about error: 'JSON_THROW' was not declared in this scope; did you mean 'JSON_TRY'? sorry i was inactive a couple of days due to college final submissions but i am free again now and would love to solve this issue
template <typename BasicJsonType> inline void throw_enum_error(const BasicJsonType& j, const char* enum_type) { JSON_THROW(::nlohmann::detail::type_error::create( 302, std::string("invalid value for ") + enum_type + ": " + j.dump(), &j)); }can i define a helper like this??
Seems reasonable to me, @nlohmann any objections?
Sure! Sorry for not answering earlier.
are my changes sufficient this time around? i will make the signoff change to avoid the DCO error also this pr has become quite messy with all my unecessary commits if you want i will submit another pr with only the necessary commits to keep things clean
@nlohmann Looks like the workflows here are awaiting approval. Not sure why since they ran before.