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 14, 2022
1 parent e80945d commit c8aa255
Show file tree
Hide file tree
Showing 12 changed files with 165 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/docset/docSet.sql
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_14', 'Macro', 'f
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');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_20', '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_NOEXCEPTION', 'Macro', 'features/macros/index.html#json_noexception');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_NO_ENUM', 'Macro', 'features/macros/index.html#json_no_enum');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_NO_IO', 'Macro', 'features/macros/index.html#json_no_io');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_SKIP_UNSUPPORTED_COMPILER_CHECK', 'Macro', 'features/macros/index.html#json_skip_unsupported_compiler_check');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_THROW_USER', 'Macro', 'features/macros/index.html#json_throw_userexception');
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 @@ -19,6 +19,7 @@ header. See also the [macro overview page](../../features/macros.md).
- [**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
- [**JSON_HAS_THREE_WAY_COMPARISON**](json_has_three_way_comparison.md) - control 3-way comparison support
- [**JSON_NO_ENUM**](json_no_enum.md) - switch off default parse/serialization functions for enums
- [**JSON_NO_IO**](json_no_io.md) - switch off functions relying on certain C++ I/O headers
- [**JSON_SKIP_UNSUPPORTED_COMPILER_CHECK**](json_skip_unsupported_compiler_check.md) - do not warn about unsupported compilers

Expand Down
135 changes: 135 additions & 0 deletions docs/mkdocs/docs/api/macros/json_no_enum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# JSON_NO_ENUM

```cpp
#define JSON_NO_ENUM
```

When defined, default parse and serialize functions for enums are excluded, you need to provide your own functions to parse/serialize enums, for example with [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) or with [`adl_serializer`](../adl_serializer/index.md).

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

This works for both unscoped and scoped enums.

## Default definition

By default, `#!cpp JSON_NO_ENUM` is not defined.

```cpp
#undef JSON_NO_ENUM
```

## 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_NO_ENUM 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_NO_ENUM defined, it does not
const json j = Choice::first;

// normally invokes from_json parse function but with JSON_NO_ENUM 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_NO_ENUM 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_NO_ENUM 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_NO_ENUM`](json_no_enum.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.
- If you want to disable enum value serialization to JSON as integers see [`JSON_NO_ENUM`](../api/macros/json_no_enum.md) which turns this default conversion into compiler error forcing you to implement conversions as described here.
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_NO_ENUM`

When defined, default parse and serialize functions for enums are excluded, you need to provide your own functions to parse/serialize enums, for example with [`NLOHMANN_JSON_SERIALIZE_ENUM`](../api/macros/nlohmann_json_serialize_enum.md).

See [full documentation of `JSON_NO_ENUM`](../api/macros/json_no_enum.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 @@ -250,6 +250,7 @@ nav:
- 'JSON_HAS_RANGES': api/macros/json_has_ranges.md
- 'JSON_HAS_THREE_WAY_COMPARISON': api/macros/json_has_three_way_comparison.md
- 'JSON_NOEXCEPTION': api/macros/json_noexception.md
- 'JSON_NO_ENUM': api/macros/json_no_enum.md
- 'JSON_NO_IO': api/macros/json_no_io.md
- 'JSON_SKIP_LIBRARY_VERSION_CHECK': api/macros/json_skip_library_version_check.md
- 'JSON_SKIP_UNSUPPORTED_COMPILER_CHECK': api/macros/json_skip_unsupported_compiler_check.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_NO_ENUM
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_NO_ENUM

// 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_NO_ENUM
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_NO_ENUM

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_NO_ENUM
#define JSON_NO_ENUM 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_NO_ENUM

#ifndef JSON_TEST_KEEP_MACROS
#undef JSON_CATCH
Expand Down
11 changes: 10 additions & 1 deletion 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_NO_ENUM
#define JSON_NO_ENUM 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_NO_ENUM
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_NO_ENUM

// 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_NO_ENUM
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_NO_ENUM

template<typename BasicJsonType>
inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
Expand Down Expand Up @@ -18555,7 +18563,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
detail::parser_callback_t<basic_json>cb = nullptr,
const bool allow_exceptions = true,
const bool ignore_comments = false
)
)
{
return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
std::move(cb), allow_exceptions, ignore_comments);
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_NO_ENUM

#ifndef JSON_TEST_KEEP_MACROS
#undef JSON_CATCH
Expand Down

0 comments on commit c8aa255

Please sign in to comment.