diff --git a/CMakeLists.txt b/CMakeLists.txt index aae5fb6e36..f20d561370 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ option(JSON_BuildTests "Build the unit tests when BUILD_TEST option(JSON_CI "Enable CI build targets." OFF) option(JSON_Diagnostics "Use extended diagnostic messages." OFF) option(JSON_ImplicitConversions "Enable implicit conversions." ON) +option(JSON_DisableEnumSerialization "Disable default integer enum serialization." OFF) option(JSON_LegacyDiscardedValueComparison "Enable legacy discarded value comparison." OFF) option(JSON_Install "Install CMake targets during install step." ${MAIN_PROJECT}) option(JSON_MultipleHeaders "Use non-amalgamated version of the library." ON) @@ -78,6 +79,10 @@ if (NOT JSON_ImplicitConversions) message(STATUS "Implicit conversions are disabled") endif() +if (JSON_DisableEnumSerialization) + message(STATUS "Enum integer serialization is disabled") +endif() + if (JSON_LegacyDiscardedValueComparison) message(STATUS "Legacy discarded value comparison enabled") endif() @@ -106,6 +111,7 @@ target_compile_definitions( ${NLOHMANN_JSON_TARGET_NAME} INTERFACE $<$>:JSON_USE_IMPLICIT_CONVERSIONS=0> + $<$:JSON_DISABLE_ENUM_SERIALIZATION=1> $<$:JSON_DIAGNOSTICS=1> $<$:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1> ) diff --git a/cmake/ci.cmake b/cmake/ci.cmake index 8704d4a54c..4fcff86aab 100644 --- a/cmake/ci.cmake +++ b/cmake/ci.cmake @@ -838,8 +838,8 @@ endfunction() ci_get_cmake(3.1.0 CMAKE_3_1_0_BINARY) ci_get_cmake(3.13.0 CMAKE_3_13_0_BINARY) -set(JSON_CMAKE_FLAGS_3_1_0 JSON_Diagnostics JSON_ImplicitConversions JSON_LegacyDiscardedValueComparison - JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind) +set(JSON_CMAKE_FLAGS_3_1_0 JSON_Diagnostics JSON_ImplicitConversions JSON_DisableEnumSerialization + JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind) set(JSON_CMAKE_FLAGS_3_13_0 JSON_BuildTests) function(ci_add_cmake_flags_targets flag min_version) diff --git a/docs/docset/docSet.sql b/docs/docset/docSet.sql index 8bd4e0678d..30c4a48de7 100644 --- a/docs/docset/docSet.sql +++ b/docs/docset/docSet.sql @@ -140,6 +140,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('SAX Interface', 'Guide', 'fea INSERT INTO searchIndex(name, type, path) VALUES ('JSON_ASSERT', 'Macro', 'features/macros/index.html#json_assertx'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_CATCH_USER', 'Macro', 'features/macros/index.html#json_catch_userexception'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTICS', 'Macro', 'features/macros/index.html#json_diagnostics'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DISABLE_ENUM_SERIALIZATION', 'Macro', 'features/macros/index.html#json_disable_enum_serialization'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_11', 'Macro', 'features/macros/index.html#json_has_cpp_11-json_has_cpp_14-json_has_cpp_17-json_has_cpp_20'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_14', 'Macro', 'features/macros/index.html#json_has_cpp_11-json_has_cpp_14-json_has_cpp_17-json_has_cpp_20'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_17', 'Macro', 'features/macros/index.html#json_has_cpp_11-json_has_cpp_14-json_has_cpp_17-json_has_cpp_20'); diff --git a/docs/mkdocs/docs/api/macros/index.md b/docs/mkdocs/docs/api/macros/index.md index 5f0a7a194d..d95869b936 100644 --- a/docs/mkdocs/docs/api/macros/index.md +++ b/docs/mkdocs/docs/api/macros/index.md @@ -29,6 +29,7 @@ header. See also the [macro overview page](../../features/macros.md). ## Type conversions +- [**JSON_DISABLE_ENUM_SERIALIZATION**](json_disable_enum_serialization.md) - switch off default serialization/deserialization functions for enums - [**JSON_USE_IMPLICIT_CONVERSIONS**](json_use_implicit_conversions.md) - control implicit conversions diff --git a/docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md b/docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md new file mode 100644 index 0000000000..60926318f2 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md @@ -0,0 +1,135 @@ +# JSON_DISABLE_ENUM_SERIALIZATION + +```cpp +#define JSON_DISABLE_ENUM_SERIALIZATION +``` + +When defined, default serialization and deserialization functions for enums are excluded and have to be provided by the user, for example, using [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) (see [arbitrary type conversions](../../features/arbitrary_types.md) for more details). + +Parsing or serializing an enum will result in a compiler error. + +This works for both unscoped and scoped enums. + +## Default definition + +By default, `#!cpp JSON_DISABLE_ENUM_SERIALIZATION` is not defined. + +```cpp +#undef JSON_DISABLE_ENUM_SERIALIZATION +``` + +## Examples + +??? example "Example 1: Disabled behavior" + + The code below forces the library **not** to create default parse/serialization functions `from_json` and `to_json`, meaning the code below **does not** compile. + + ```cpp + #define JSON_DISABLE_ENUM_SERIALIZATION 1 + #include + + using json = nlohmann::json; + + enum class Choice + { + first, + second, + }; + + int main() + { + // normally invokes to_json serialization function but with JSON_DISABLE_ENUM_SERIALIZATION defined, it does not + const json j = Choice::first; + + // normally invokes from_json parse function but with JSON_DISABLE_ENUM_SERIALIZATION defined, it does not + Choice ch = j.get(); + } + ``` + +??? example "Example 2: Serialize enum macro" + + The code below forces the library **not** to create default parse/serialization functions `from_json` and `to_json`, but uses [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) to parse and serialize the enum. + + ```cpp + #define JSON_DISABLE_ENUM_SERIALIZATION 1 + #include + + using json = nlohmann::json; + + enum class Choice + { + first, + second, + }; + + NLOHMANN_JSON_SERIALIZE_ENUM(Choice, + { + { Choice::first, "first" }, + { Choice::second, "second" }, + }) + + int main() + { + // uses user-defined to_json function defined by macro + const json j = Choice::first; + + // uses user-defined from_json function defined by macro + Choice ch = j.get(); + } + ``` + +??? example "Example 3: User-defined parse/serialization functions" + + The code below forces the library **not** to create default parse/serialization functions `from_json` and `to_json`, but uses user-defined functions to parse and serialize the enum. + + ```cpp + #define JSON_DISABLE_ENUM_SERIALIZATION 1 + #include + + using json = nlohmann::json; + + enum class Choice + { + first, + second, + }; + + void from_json(const json& j, Choice& ch) + { + auto value = j.get(); + if (value == "first") + { + ch = Choice::first; + } + else if (value == "second") + { + ch = Choice::second; + } + } + + void to_json(json& j, const Choice& ch) + { + auto value = j.get(); + if (value == "first") + { + ch = Choice::first; + } + else if (value == "second") + { + ch = Choice::second; + } + } + + int main() + { + // uses user-defined to_json function + const json j = Choice::first; + + // uses user-defined from_json function + Choice ch = j.get(); + } + ``` + +## See also + +- [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) \ No newline at end of file diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md index 7b0f898021..b7204a8088 100644 --- a/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md @@ -78,6 +78,7 @@ inline void from_json(const BasicJsonType& j, type& e); ## See also - [Specializing enum conversion](../../features/enum_conversion.md) +- [`JSON_DISABLE_ENUM_SERIALIZATION`](json_disable_enum_serialization.md) ## Version history diff --git a/docs/mkdocs/docs/features/enum_conversion.md b/docs/mkdocs/docs/features/enum_conversion.md index 7e61f67bb8..59ffbd5f11 100644 --- a/docs/mkdocs/docs/features/enum_conversion.md +++ b/docs/mkdocs/docs/features/enum_conversion.md @@ -58,3 +58,4 @@ Other Important points: default pair carefully. - If an enum or JSON value is specified more than once in your map, the first matching occurrence from the top of the map will be returned when converting to or from JSON. +- To disable the default serialization of enumerators as integers and force a compiler error instead, see [`JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md). diff --git a/docs/mkdocs/docs/features/macros.md b/docs/mkdocs/docs/features/macros.md index e04a426a54..1be95d35d5 100644 --- a/docs/mkdocs/docs/features/macros.md +++ b/docs/mkdocs/docs/features/macros.md @@ -54,6 +54,12 @@ Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`. See [full documentation of `JSON_NOEXCEPTION`](../api/macros/json_noexception.md). +## `JSON_DISABLE_ENUM_SERIALIZATION` + +When defined, default parse and serialize functions for enums are excluded and have to be provided by the user, for example, using [`NLOHMANN_JSON_SERIALIZE_ENUM`](../api/macros/nlohmann_json_serialize_enum.md). + +See [full documentation of `JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md). + ## `JSON_NO_IO` When defined, headers ``, ``, ``, ``, and `` are not included and parse functions diff --git a/docs/mkdocs/mkdocs.yml b/docs/mkdocs/mkdocs.yml index 08ef336db6..c583ed78fe 100644 --- a/docs/mkdocs/mkdocs.yml +++ b/docs/mkdocs/mkdocs.yml @@ -241,6 +241,7 @@ nav: - 'JSON_ASSERT': api/macros/json_assert.md - 'JSON_CATCH_USER': api/macros/json_throw_user.md - 'JSON_DIAGNOSTICS': api/macros/json_diagnostics.md + - 'JSON_DISABLE_ENUM_SERIALIZATION': api/macros/json_disable_enum_serialization.md - 'JSON_HAS_CPP_11': api/macros/json_has_cpp_11.md - 'JSON_HAS_CPP_14': api/macros/json_has_cpp_11.md - 'JSON_HAS_CPP_17': api/macros/json_has_cpp_11.md diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index f0a93f2918..ed4e6de5f3 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -139,6 +139,7 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_int get_arithmetic_value(j, val); } +#if !JSON_DISABLE_ENUM_SERIALIZATION template::value, int> = 0> inline void from_json(const BasicJsonType& j, EnumType& e) @@ -147,6 +148,7 @@ inline void from_json(const BasicJsonType& j, EnumType& e) get_arithmetic_value(j, val); e = static_cast(val); } +#endif // JSON_DISABLE_ENUM_SERIALIZATION // forward_list doesn't have an insert method template::construct(j, static_cast(val)); } +#if !JSON_DISABLE_ENUM_SERIALIZATION template::value, int> = 0> inline void to_json(BasicJsonType& j, EnumType e) noexcept @@ -320,6 +321,7 @@ inline void to_json(BasicJsonType& j, EnumType e) noexcept using underlying_type = typename std::underlying_type::type; external_constructor::construct(j, static_cast(e)); } +#endif // JSON_DISABLE_ENUM_SERIALIZATION template inline void to_json(BasicJsonType& j, const std::vector& e) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 18a527c195..706f1b9714 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -456,3 +456,7 @@ #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 #endif + +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif diff --git a/include/nlohmann/detail/macro_unscope.hpp b/include/nlohmann/detail/macro_unscope.hpp index 396fe1a334..09f677b3d8 100644 --- a/include/nlohmann/detail/macro_unscope.hpp +++ b/include/nlohmann/detail/macro_unscope.hpp @@ -16,6 +16,7 @@ #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL #undef JSON_INLINE_VARIABLE #undef JSON_NO_UNIQUE_ADDRESS +#undef JSON_DISABLE_ENUM_SERIALIZATION #ifndef JSON_TEST_KEEP_MACROS #undef JSON_CATCH diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 4a9c4bf830..98c8dd664c 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2684,6 +2684,10 @@ using is_detected_convertible = #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 #endif +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif + #if JSON_HAS_THREE_WAY_COMPARISON #include // partial_ordering #endif @@ -4384,6 +4388,7 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_int get_arithmetic_value(j, val); } +#if !JSON_DISABLE_ENUM_SERIALIZATION template::value, int> = 0> inline void from_json(const BasicJsonType& j, EnumType& e) @@ -4392,6 +4397,7 @@ inline void from_json(const BasicJsonType& j, EnumType& e) get_arithmetic_value(j, val); e = static_cast(val); } +#endif // JSON_DISABLE_ENUM_SERIALIZATION // forward_list doesn't have an insert method template::construct(j, static_cast(val)); } +#if !JSON_DISABLE_ENUM_SERIALIZATION template::value, int> = 0> inline void to_json(BasicJsonType& j, EnumType e) noexcept @@ -5301,6 +5308,7 @@ inline void to_json(BasicJsonType& j, EnumType e) noexcept using underlying_type = typename std::underlying_type::type; external_constructor::construct(j, static_cast(e)); } +#endif // JSON_DISABLE_ENUM_SERIALIZATION template inline void to_json(BasicJsonType& j, const std::vector& e) @@ -23580,6 +23588,7 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL #undef JSON_INLINE_VARIABLE #undef JSON_NO_UNIQUE_ADDRESS +#undef JSON_DISABLE_ENUM_SERIALIZATION #ifndef JSON_TEST_KEEP_MACROS #undef JSON_CATCH