From 68beba727c7e874af945484c7748294f23c5b82f Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 30 Sep 2026 20:06:46 +0200 Subject: [PATCH] Fix from_json() for enums with underlying type bool (#5679) get_arithmetic_value() rejects boolean_t, so the default from_json() for enums failed to compile for an enum whose underlying type is bool (e.g. enum class Flag : bool { off, on }), even though the matching to_json() serializes such enums as an unsigned number. Read the underlying value through number_unsigned_t in that case, matching what to_json() writes, then cast back to the underlying type before constructing the enum. Fixes #5671. Signed-off-by: Niels Lohmann --- include/nlohmann/detail/conversions/from_json.hpp | 8 ++++++-- single_include/nlohmann/json.hpp | 8 ++++++-- tests/src/unit-conversions.cpp | 8 ++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 11e40f5f4..6ecf7e657 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -167,9 +167,13 @@ template::value, int> = 0> inline void from_json(const BasicJsonType& j, EnumType& e) { - typename std::underlying_type::type val; + using underlying_type = typename std::underlying_type::type; + // get_arithmetic_value() does not accept boolean_t; read the number that to_json() wrote instead + using value_type = typename std::conditional::value, + typename BasicJsonType::number_unsigned_t, underlying_type>::type; + value_type val; get_arithmetic_value(j, val); - e = static_cast(val); + e = static_cast(static_cast(val)); } #endif // JSON_DISABLE_ENUM_SERIALIZATION diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 73c8ab9be..9a9d6ae0c 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -5664,9 +5664,13 @@ template::value, int> = 0> inline void from_json(const BasicJsonType& j, EnumType& e) { - typename std::underlying_type::type val; + using underlying_type = typename std::underlying_type::type; + // get_arithmetic_value() does not accept boolean_t; read the number that to_json() wrote instead + using value_type = typename std::conditional::value, + typename BasicJsonType::number_unsigned_t, underlying_type>::type; + value_type val; get_arithmetic_value(j, val); - e = static_cast(val); + e = static_cast(static_cast(val)); } #endif // JSON_DISABLE_ENUM_SERIALIZATION diff --git a/tests/src/unit-conversions.cpp b/tests/src/unit-conversions.cpp index 90d972f71..077ba0e14 100644 --- a/tests/src/unit-conversions.cpp +++ b/tests/src/unit-conversions.cpp @@ -1358,6 +1358,14 @@ TEST_CASE("value conversion") CHECK(json(value_1).get() == value_1); CHECK(json(cpp_enum::value_1).get() == cpp_enum::value_1); } + + SECTION("get an enum with underlying type bool (#5671)") + { + enum class bool_enum : bool { off, on }; + + CHECK(json(bool_enum::off).get() == bool_enum::off); + CHECK(json(bool_enum::on).get() == bool_enum::on); + } #endif SECTION("more involved conversions")