Skip to content

Commit

Permalink
Allow disabling default enum conversions
Browse files Browse the repository at this point in the history
  • Loading branch information
richardhozak committed Jun 16, 2022
1 parent e80945d commit 99facc2
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -106,6 +111,7 @@ target_compile_definitions(
${NLOHMANN_JSON_TARGET_NAME}
INTERFACE
$<$<NOT:$<BOOL:${JSON_ImplicitConversions}>>:JSON_USE_IMPLICIT_CONVERSIONS=0>
$<$<BOOL:${JSON_DisableEnumSerialization}>:JSON_DISABLE_ENUM_SERIALIZATION=1>
$<$<BOOL:${JSON_Diagnostics}>:JSON_DIAGNOSTICS=1>
$<$<BOOL:${JSON_LegacyDiscardedValueComparison}>:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1>
)
Expand Down
4 changes: 2 additions & 2 deletions cmake/ci.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions docs/docset/docSet.sql
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
1 change: 1 addition & 0 deletions docs/mkdocs/docs/api/macros/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ header. See also the [macro overview page](../../features/macros.md).

## Language support

- [**JSON_DISABLE_ENUM_SERIALIZATION**](json_disable_enum_serialization.md) - switch off default parse/serialization functions for enums
- [**JSON_HAS_CPP_11**<br>**JSON_HAS_CPP_14**<br>**JSON_HAS_CPP_17**<br>**JSON_HAS_CPP_20**](json_has_cpp_11.md) - set supported C++ standard
- [**JSON_HAS_FILESYSTEM**<br>**JSON_HAS_EXPERIMENTAL_FILESYSTEM**](json_has_filesystem.md) - control `std::filesystem` support
- [**JSON_HAS_RANGES**](json_has_ranges.md) - control `std::ranges` support
Expand Down
135 changes: 135 additions & 0 deletions docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# JSON_DISABLE_ENUM_SERIALIZATION

```cpp
#define 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`](nlohmann_json_serialize_enum.md) (see [arbitrary type conversions](../../features/arbitrary_types.md) for more details).

If you would try to parse or serialize enum you would get a compiler error, forcing you to implement enum serialization.

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 <nlohmann/json.hpp>

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<Choice>();
}
```

??? 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 <nlohmann/json.hpp>

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<Choice>();
}
```

??? 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 <nlohmann/json.hpp>

using json = nlohmann::json;

enum class Choice
{
first,
second,
};

void from_json(const json& j, Choice& ch)
{
auto value = j.get<std::string>();
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<std::string>();
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<Choice>();
}
```

## See also

- [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md)
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions docs/mkdocs/docs/features/enum_conversion.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
6 changes: 6 additions & 0 deletions docs/mkdocs/docs/features/macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<cstdio>`, `<ios>`, `<iosfwd>`, `<istream>`, and `<ostream>` are not included and parse functions
Expand Down
1 change: 1 addition & 0 deletions docs/mkdocs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions include/nlohmann/detail/conversions/from_json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<typename BasicJsonType, typename EnumType,
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
inline void from_json(const BasicJsonType& j, EnumType& e)
Expand All @@ -147,6 +148,7 @@ inline void from_json(const BasicJsonType& j, EnumType& e)
get_arithmetic_value(j, val);
e = static_cast<EnumType>(val);
}
#endif // JSON_DISABLE_ENUM_SERIALIZATION

// forward_list doesn't have an insert method
template<typename BasicJsonType, typename T, typename Allocator,
Expand Down
2 changes: 2 additions & 0 deletions include/nlohmann/detail/conversions/to_json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,13 +313,15 @@ inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
}

#if !JSON_DISABLE_ENUM_SERIALIZATION
template<typename BasicJsonType, typename EnumType,
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
inline void to_json(BasicJsonType& j, EnumType e) noexcept
{
using underlying_type = typename std::underlying_type<EnumType>::type;
external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
}
#endif // JSON_DISABLE_ENUM_SERIALIZATION

template<typename BasicJsonType>
inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
Expand Down
4 changes: 4 additions & 0 deletions include/nlohmann/detail/macro_scope.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions include/nlohmann/detail/macro_unscope.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <compare> // partial_ordering
#endif
Expand Down Expand Up @@ -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<typename BasicJsonType, typename EnumType,
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
inline void from_json(const BasicJsonType& j, EnumType& e)
Expand All @@ -4392,6 +4397,7 @@ inline void from_json(const BasicJsonType& j, EnumType& e)
get_arithmetic_value(j, val);
e = static_cast<EnumType>(val);
}
#endif // JSON_DISABLE_ENUM_SERIALIZATION

// forward_list doesn't have an insert method
template<typename BasicJsonType, typename T, typename Allocator,
Expand Down Expand Up @@ -5294,13 +5300,15 @@ inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
}

#if !JSON_DISABLE_ENUM_SERIALIZATION
template<typename BasicJsonType, typename EnumType,
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
inline void to_json(BasicJsonType& j, EnumType e) noexcept
{
using underlying_type = typename std::underlying_type<EnumType>::type;
external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
}
#endif // JSON_DISABLE_ENUM_SERIALIZATION

template<typename BasicJsonType>
inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 99facc2

Please sign in to comment.