This commit is contained in:
amirghaz 2025-02-22 06:11:24 +01:00 committed by GitHub
commit 475199842d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 212 additions and 14 deletions

View File

@ -372,8 +372,9 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t&
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
}
template<typename BasicJsonType, typename ConstructibleObjectType,
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
template < typename BasicJsonType, typename ConstructibleObjectType,
enable_if_t < is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value&&
!std::is_enum<typename ConstructibleObjectType::key_type>::value, int > = 0 >
inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
@ -394,6 +395,23 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
obj = std::move(ret);
}
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
enable_if_t < is_constructible_object_type<BasicJsonType, std::map<Key, Value, Compare, Allocator>>::value&&
is_compatible_object_type<BasicJsonType, std::map<Key, Value, Compare, Allocator>>::value&&
std::is_enum<Key>::value, int > = 0 >
inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
{
JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
}
m.clear();
for (const auto& p : j.items())
{
m.emplace(string_to_enum(json(p.key()), Key()), p.value().template get<Value>());
}
}
// overload for arithmetic types, not chosen for basic_json template arguments
// (BooleanType, etc..); note: Is it really necessary to provide explicit
// overloads for boolean_t etc. in case of a custom BooleanType which is not
@ -493,7 +511,8 @@ auto from_json(BasicJsonType&& j, TupleRelated&& t)
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
typename = enable_if_t < !std::is_constructible <
typename BasicJsonType::string_t, Key >::value >>
typename BasicJsonType::string_t, Key >::value &&
!is_compatible_object_type<BasicJsonType, std::map<Key, Value, Compare, Allocator>>::value >>
inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))

View File

@ -21,6 +21,7 @@
#include <utility> // move, forward, declval, pair
#include <valarray> // valarray
#include <vector> // vector
#include <map> // map
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
@ -245,8 +246,34 @@ struct external_constructor<value_t::object>
j.assert_invariant();
}
template < typename BasicJsonType, typename Key, typename Value,
enable_if_t < is_compatible_object_type<BasicJsonType, std::map<Key, Value>>::value&&
!is_basic_json<std::map<Key, Value>>::value&&
std::is_enum<Key>::value, int > = 0 >
static void construct(BasicJsonType& j, const std::map<Key, Value>& obj)
{
using std::begin;
using std::end;
std::map<std::string, Value> temp;
for (auto& i : obj)
{
Key first = i.first;
Value second = i.second;
temp.insert({ enum_to_string(j, first), second });
}
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::object;
j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(temp), end(temp));
j.set_parents();
j.assert_invariant();
}
template < typename BasicJsonType, typename CompatibleObjectType,
enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value&&
is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&&
!is_basic_json<CompatibleObjectType>::value&&
!std::is_enum<typename CompatibleObjectType::key_type>::value, int > = 0 >
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
{
using std::begin;
@ -384,12 +411,23 @@ inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
}
template < typename BasicJsonType, typename CompatibleObjectType,
enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&&
!is_basic_json<CompatibleObjectType>::value&&
!std::is_enum<typename CompatibleObjectType::key_type>::value, int > = 0 >
inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
{
external_constructor<value_t::object>::construct(j, obj);
}
template < typename BasicJsonType, typename Key, typename Value,
enable_if_t < is_compatible_object_type<BasicJsonType, std::map<Key, Value>>::value&&
!is_basic_json<std::map<Key, Value>>::value&&
std::is_enum<Key>::value, int > = 0 >
inline void to_json(BasicJsonType& j, const std::map<Key, Value>& obj)
{
external_constructor<value_t::object>::construct(j, obj);
}
template<typename BasicJsonType>
inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
{

View File

@ -240,7 +240,47 @@
return ej_pair.second == j; \
}); \
e = ((it != std::end(m)) ? it : std::begin(m))->first; \
} \
/* Function to check for serialized ENUM type */ \
template<typename BasicJsonType> \
inline constexpr bool serialized(BasicJsonType& j, ENUM_TYPE e) \
{ \
return true; \
} \
template<typename BasicJsonType> \
inline std::string enum_to_string(BasicJsonType j, ENUM_TYPE e) \
{ \
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.first == e; \
}); \
return ((it != std::end(m)) ? it : std::begin(m))->second; \
} \
template<typename BasicJsonType> \
inline ENUM_TYPE string_to_enum(BasicJsonType j, ENUM_TYPE e) \
{ \
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.second == j; \
}); \
return ((it != std::end(m)) ? it : std::begin(m))->first; \
}
// Function to check for non-serialized ENUM type
template<typename BasicJsonType, typename EnumType>
inline constexpr bool serialized(BasicJsonType& j, EnumType e)
{
return false;
}
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
// may be removed in the future once the class is split.

View File

@ -357,8 +357,10 @@ struct is_compatible_object_type_impl <
// macOS's is_constructible does not play well with nonesuch...
static constexpr bool value =
is_constructible<typename object_t::key_type,
typename CompatibleObjectType::key_type>::value &&
(is_constructible<typename object_t::key_type,
typename CompatibleObjectType::key_type>::value ||
(std::is_enum<typename CompatibleObjectType::key_type>::value &&
serialized("", typename CompatibleObjectType::key_type()))) &&
is_constructible<typename object_t::mapped_type,
typename CompatibleObjectType::mapped_type>::value;
};

View File

@ -2606,7 +2606,47 @@ JSON_HEDLEY_DIAGNOSTIC_POP
return ej_pair.second == j; \
}); \
e = ((it != std::end(m)) ? it : std::begin(m))->first; \
} \
/* Function to check for serialized ENUM type */ \
template<typename BasicJsonType> \
inline constexpr bool serialized(BasicJsonType& j, ENUM_TYPE e) \
{ \
return true; \
} \
template<typename BasicJsonType> \
inline std::string enum_to_string(BasicJsonType j, ENUM_TYPE e) \
{ \
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.first == e; \
}); \
return ((it != std::end(m)) ? it : std::begin(m))->second; \
} \
template<typename BasicJsonType> \
inline ENUM_TYPE string_to_enum(BasicJsonType j, ENUM_TYPE e) \
{ \
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.second == j; \
}); \
return ((it != std::end(m)) ? it : std::begin(m))->first; \
}
// Function to check for non-serialized ENUM type
template<typename BasicJsonType, typename EnumType>
inline constexpr bool serialized(BasicJsonType& j, EnumType e)
{
return false;
}
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
// may be removed in the future once the class is split.
@ -3892,8 +3932,10 @@ struct is_compatible_object_type_impl <
// macOS's is_constructible does not play well with nonesuch...
static constexpr bool value =
is_constructible<typename object_t::key_type,
typename CompatibleObjectType::key_type>::value &&
(is_constructible<typename object_t::key_type,
typename CompatibleObjectType::key_type>::value ||
(std::is_enum<typename CompatibleObjectType::key_type>::value &&
serialized("", typename CompatibleObjectType::key_type()))) &&
is_constructible<typename object_t::mapped_type,
typename CompatibleObjectType::mapped_type>::value;
};
@ -5152,8 +5194,9 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t&
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
}
template<typename BasicJsonType, typename ConstructibleObjectType,
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
template < typename BasicJsonType, typename ConstructibleObjectType,
enable_if_t < is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value&&
!std::is_enum<typename ConstructibleObjectType::key_type>::value, int > = 0 >
inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
@ -5174,6 +5217,23 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
obj = std::move(ret);
}
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
enable_if_t < is_constructible_object_type<BasicJsonType, std::map<Key, Value, Compare, Allocator>>::value&&
is_compatible_object_type<BasicJsonType, std::map<Key, Value, Compare, Allocator>>::value&&
std::is_enum<Key>::value, int > = 0 >
inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
{
JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
}
m.clear();
for (const auto& p : j.items())
{
m.emplace(string_to_enum(json(p.key()), Key()), p.value().template get<Value>());
}
}
// overload for arithmetic types, not chosen for basic_json template arguments
// (BooleanType, etc..); note: Is it really necessary to provide explicit
// overloads for boolean_t etc. in case of a custom BooleanType which is not
@ -5273,7 +5333,8 @@ auto from_json(BasicJsonType&& j, TupleRelated&& t)
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
typename = enable_if_t < !std::is_constructible <
typename BasicJsonType::string_t, Key >::value >>
typename BasicJsonType::string_t, Key >::value &&
!is_compatible_object_type<BasicJsonType, std::map<Key, Value, Compare, Allocator>>::value >>
inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
@ -5376,6 +5437,7 @@ NLOHMANN_JSON_NAMESPACE_END
#include <utility> // move, forward, declval, pair
#include <valarray> // valarray
#include <vector> // vector
#include <map> // map
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
// __ _____ _____ _____
@ -5882,8 +5944,34 @@ struct external_constructor<value_t::object>
j.assert_invariant();
}
template < typename BasicJsonType, typename Key, typename Value,
enable_if_t < is_compatible_object_type<BasicJsonType, std::map<Key, Value>>::value&&
!is_basic_json<std::map<Key, Value>>::value&&
std::is_enum<Key>::value, int > = 0 >
static void construct(BasicJsonType& j, const std::map<Key, Value>& obj)
{
using std::begin;
using std::end;
std::map<std::string, Value> temp;
for (auto& i : obj)
{
Key first = i.first;
Value second = i.second;
temp.insert({ enum_to_string(j, first), second });
}
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::object;
j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(temp), end(temp));
j.set_parents();
j.assert_invariant();
}
template < typename BasicJsonType, typename CompatibleObjectType,
enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value&&
is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&&
!is_basic_json<CompatibleObjectType>::value&&
!std::is_enum<typename CompatibleObjectType::key_type>::value, int > = 0 >
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
{
using std::begin;
@ -6021,12 +6109,23 @@ inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
}
template < typename BasicJsonType, typename CompatibleObjectType,
enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&&
!is_basic_json<CompatibleObjectType>::value&&
!std::is_enum<typename CompatibleObjectType::key_type>::value, int > = 0 >
inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
{
external_constructor<value_t::object>::construct(j, obj);
}
template < typename BasicJsonType, typename Key, typename Value,
enable_if_t < is_compatible_object_type<BasicJsonType, std::map<Key, Value>>::value&&
!is_basic_json<std::map<Key, Value>>::value&&
std::is_enum<Key>::value, int > = 0 >
inline void to_json(BasicJsonType& j, const std::map<Key, Value>& obj)
{
external_constructor<value_t::object>::construct(j, obj);
}
template<typename BasicJsonType>
inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
{