Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
3404955
fix: throw type_error.302 on unknown enum JSON value (fixes #3992)
Ash-Jose Nov 4, 2025
e87fbc3
chore: regenerate single-header after enum deserialization fix
Ash-Jose Nov 4, 2025
382367d
add NLOHMANN_JSON_SERIALIZE_ENUM_STRICT macro that throws on unknown …
Ash-Jose Nov 4, 2025
3d0e74c
style: apply concat() suggestion and rerun make amalgamate
Ash-Jose Nov 5, 2025
cb710cc
style: apply concat() suggestion and rerun make amalgamate
Ash-Jose Nov 5, 2025
216a636
fix: include string_concat.hpp and correct concat() usage in NLOHMANN…
Ash-Jose Nov 5, 2025
7863aa3
made few formatting changes in macro_scope.hpp
Ash-Jose Nov 5, 2025
3155e6a
ran make amalgamate again
Ash-Jose Nov 5, 2025
a0fc73b
revert to std::string() concat in enum strict macro
Ash-Jose Nov 5, 2025
88e36cb
fix: include exceptions.hpp for type_error in enum strict macro
Ash-Jose Nov 5, 2025
e07de0e
fix: add forward declaration for type_error to avoid circular include
Ash-Jose Nov 5, 2025
31c67e3
fix: make NLOHMANN_JSON_SERIALIZE_ENUM_STRICT throw type_error on unk…
Ash-Jose Nov 5, 2025
8c13504
minor formatting changes
Ash-Jose Nov 5, 2025
9882be4
removed test,json which was left there by accident
Ash-Jose Nov 5, 2025
780df1a
changed formatting of unit-serialize_enum_strict.cpp and amalgamated
Ash-Jose Nov 5, 2025
a6a57cd
fix: throw type_error.302 on unknown enum JSON value (fixes #3992)
Ash-Jose Nov 4, 2025
fc2effb
chore: regenerate single-header after enum deserialization fix
Ash-Jose Nov 4, 2025
07b7f67
add NLOHMANN_JSON_SERIALIZE_ENUM_STRICT macro that throws on unknown …
Ash-Jose Nov 4, 2025
ac5e684
style: apply concat() suggestion and rerun make amalgamate
Ash-Jose Nov 5, 2025
576975f
style: apply concat() suggestion and rerun make amalgamate
Ash-Jose Nov 5, 2025
893b4e8
fix: include string_concat.hpp and correct concat() usage in NLOHMANN…
Ash-Jose Nov 5, 2025
512f4b4
made few formatting changes in macro_scope.hpp
Ash-Jose Nov 5, 2025
f6bc704
ran make amalgamate again
Ash-Jose Nov 5, 2025
d4f8289
revert to std::string() concat in enum strict macro
Ash-Jose Nov 5, 2025
08f8570
fix: include exceptions.hpp for type_error in enum strict macro
Ash-Jose Nov 5, 2025
089e0bf
fix: add forward declaration for type_error to avoid circular include
Ash-Jose Nov 5, 2025
4f4ac7f
fix: make NLOHMANN_JSON_SERIALIZE_ENUM_STRICT throw type_error on unk…
Ash-Jose Nov 5, 2025
c69f8d3
minor formatting changes
Ash-Jose Nov 5, 2025
c9b5137
removed test,json which was left there by accident
Ash-Jose Nov 5, 2025
97ef95f
changed formatting of unit-serialize_enum_strict.cpp and amalgamated
Ash-Jose Nov 5, 2025
638ec5f
aesthetic changes and included doctest_compatibility.h
Ash-Jose Nov 12, 2025
895d38e
changed position of string include in macro_scope.hpp
Ash-Jose Nov 12, 2025
ff46319
amalgamated
Ash-Jose Nov 12, 2025
988fdef
Merge branch 'nlohmann:develop' into fix/enum-deser-throw-on-unknown
Ash-Jose Nov 13, 2025
37018c1
change github branch to match local
Ash-Jose Nov 13, 2025
94ef0ce
resolving merge conflict
Ash-Jose Nov 13, 2025
d792400
removed merge conflicts again
Ash-Jose Nov 13, 2025
5944257
added helper function
Ash-Jose Nov 13, 2025
677f5d9
formatting and correcting the helper
Ash-Jose Nov 13, 2025
1231904
migrated helper to include/nlohmann/detail/conversions/from_json.hpp
Ash-Jose Nov 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions include/nlohmann/detail/conversions/from_json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@
#include <nlohmann/detail/string_concat.hpp>
#include <nlohmann/detail/value_t.hpp>

/* helper for strict enum error reporting */
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));
}

// include after macro_scope.hpp
#ifdef JSON_HAS_CPP_17
#include <optional> // optional
Expand Down
42 changes: 42 additions & 0 deletions include/nlohmann/detail/macro_scope.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#pragma once

#include <string>
#include <utility> // declval, pair
#include <nlohmann/detail/meta/detected.hpp>
#include <nlohmann/thirdparty/hedley/hedley.hpp>
Expand Down Expand Up @@ -253,6 +254,47 @@
e = ((it != std::end(m)) ? it : std::begin(m))->first; \
}

/*!
@brief macro to briefly define a mapping between an enum and JSON (strict version)
@def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT
@since version 3.12.0
*/

#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \
template<typename BasicJsonType> \
inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
{ \
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.first == e; \
}); \
j = ((it != std::end(m)) ? it : std::begin(m))->second; \
} \
template<typename BasicJsonType> \
inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
{ \
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.second == j; \
}); \
if (it != std::end(m)) \
{ \
e = it->first; \
return; \
} \
throw_enum_error(j, #ENUM_TYPE); \
}

// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
// may be removed in the future once the class is split.

Expand Down
52 changes: 52 additions & 0 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@



#include <string>
#include <utility> // declval, pair
// #include <nlohmann/detail/meta/detected.hpp>
// __ _____ _____ _____
Expand Down Expand Up @@ -2617,6 +2618,47 @@ JSON_HEDLEY_DIAGNOSTIC_POP
e = ((it != std::end(m)) ? it : std::begin(m))->first; \
}

/*!
@brief macro to briefly define a mapping between an enum and JSON (strict version)
@def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT
@since version 3.12.0
*/

#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \
template<typename BasicJsonType> \
inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
{ \
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.first == e; \
}); \
j = ((it != std::end(m)) ? it : std::begin(m))->second; \
} \
template<typename BasicJsonType> \
inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
{ \
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.second == j; \
}); \
if (it != std::end(m)) \
{ \
e = it->first; \
return; \
} \
throw_enum_error(j, #ENUM_TYPE); \
}

// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
// may be removed in the future once the class is split.

Expand Down Expand Up @@ -4862,6 +4904,16 @@ NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/value_t.hpp>


/* helper for strict enum error reporting */
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));
}

// include after macro_scope.hpp
#ifdef JSON_HAS_CPP_17
#include <optional> // optional
Expand Down
40 changes: 40 additions & 0 deletions tests/src/unit-serialize_enum_strict.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT

#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>

using json = nlohmann::json;

namespace ns
{
enum class Color { red, green, blue, unknown };

NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(Color,
{
{ Color::unknown, "unknown" },
{ Color::red, "red" },
{ Color::green, "green" },
{ Color::blue, "blue" }
})
} // namespace ns

TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM_STRICT throws on unknown input string")
{
json j = "purple"; // not mapped
ns::Color c;

CHECK_THROWS_AS((j.get_to(c)), nlohmann::detail::type_error);
}

TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM_STRICT still deserializes valid values")
{
json j = "green";
auto c = j.get<ns::Color>();
CHECK(c == ns::Color::green);
}
Loading