Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add strict enum de/serialization macro #4612

Open
wants to merge 13 commits into
base: develop
Choose a base branch
from
34 changes: 32 additions & 2 deletions include/nlohmann/detail/macro_scope.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,36 @@

#include <nlohmann/detail/abi_macros.hpp>

NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
template<typename T>
[[noreturn]] inline void throw_if_exceptions_enabled(T&& exception)
{
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND) || defined(EXCEPTIONS)
hnampally marked this conversation as resolved.
Show resolved Hide resolved
throw std::forward<T>(exception);
#else
// Forward the exception (even if unused) and abort
std::forward<T>(exception);
std::abort();
#endif
}
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END

// exclude unsupported compilers
#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
hnampally marked this conversation as resolved.
Show resolved Hide resolved
#if defined(__clang__)
#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
#endif
#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
#endif
#endif
#endif

// exclude unsupported compilers
#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
#if defined(__clang__)
Expand Down Expand Up @@ -262,7 +292,7 @@
}); \
if (it == std::end(m)) { \
auto value = static_cast<typename std::underlying_type<ENUM_TYPE>::type>(e); \
JSON_THROW(nlohmann::detail::type_error::create(302, nlohmann::detail::concat("can't serialize - enum value ", std::to_string(value), " out of range"), &j)); \
nlohmann::detail::throw_if_exceptions_enabled(nlohmann::detail::type_error::create(302, nlohmann::detail::concat("can't serialize - enum value ", std::to_string(value), " out of range"), &j)); \
} \
j = it->second; \
} \
Expand All @@ -279,7 +309,7 @@
return ej_pair.second == j; \
}); \
if (it == std::end(m)) \
JSON_THROW(nlohmann::detail::type_error::create(302, nlohmann::detail::concat("can't deserialize - invalid json value : ", j.dump()), &j)); \
nlohmann::detail::throw_if_exceptions_enabled(nlohmann::detail::type_error::create(302, nlohmann::detail::concat("can't deserialize - invalid json value : ", j.dump()), &j)); \
e = it->first; \
}

Expand Down
34 changes: 32 additions & 2 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2383,6 +2383,36 @@ JSON_HEDLEY_DIAGNOSTIC_POP
// #include <nlohmann/detail/abi_macros.hpp>


NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
template<typename T>
[[noreturn]] inline void throw_if_exceptions_enabled(T&& exception)
{
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND) || defined(EXCEPTIONS)
throw std::forward<T>(exception);
#else
// Forward the exception (even if unused) and abort
std::forward<T>(exception);
std::abort();
#endif
}
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END

// exclude unsupported compilers
#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
#if defined(__clang__)
#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
#endif
#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
#endif
#endif
#endif

// exclude unsupported compilers
#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
#if defined(__clang__)
Expand Down Expand Up @@ -2628,7 +2658,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP
}); \
if (it == std::end(m)) { \
auto value = static_cast<typename std::underlying_type<ENUM_TYPE>::type>(e); \
JSON_THROW(nlohmann::detail::type_error::create(302, nlohmann::detail::concat("can't serialize - enum value ", std::to_string(value), " out of range"), &j)); \
nlohmann::detail::throw_if_exceptions_enabled(nlohmann::detail::type_error::create(302, nlohmann::detail::concat("can't serialize - enum value ", std::to_string(value), " out of range"), &j)); \
} \
j = it->second; \
} \
Expand All @@ -2645,7 +2675,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP
return ej_pair.second == j; \
}); \
if (it == std::end(m)) \
JSON_THROW(nlohmann::detail::type_error::create(302, nlohmann::detail::concat("can't deserialize - invalid json value : ", j.dump()), &j)); \
nlohmann::detail::throw_if_exceptions_enabled(nlohmann::detail::type_error::create(302, nlohmann::detail::concat("can't deserialize - invalid json value : ", j.dump()), &j)); \
e = it->first; \
}

Expand Down
10 changes: 0 additions & 10 deletions tests/src/unit-conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1657,13 +1657,6 @@ TEST_CASE("JSON to enum mapping")
}
}

#if !defined(JSON_NOEXCEPTION) && !defined(JSON_THROW_USER) && !defined(JSON_THROW)
#define JSON_THROW(exception) throw exception
#else
#include <cstdlib>
#define JSON_THROW(exception) std::abort()
#endif

enum class cards_strict {kreuz, pik, herz, karo};

// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive
Expand Down Expand Up @@ -1729,9 +1722,6 @@ TEST_CASE("JSON to enum mapping")
CHECK_THROWS_WITH_AS(j.template get<TaskStateStrict>(), "[json.exception.type_error.302] can't deserialize - invalid json value : \"foo\"", json::type_error);
}
}
#if defined(JSON_THROW)
#undef JSON_THROW
#endif

#ifdef JSON_HAS_CPP_17
#ifndef JSON_USE_IMPLICIT_CONVERSIONS
Expand Down
Loading