Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
json
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
json
Commits
9294e25c
Unverified
Commit
9294e25c
authored
Oct 18, 2018
by
Niels Lohmann
Committed by
GitHub
Oct 18, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1301 from theodelrieu/fix/1299
add new is_constructible_* traits used in from_json
parents
b553a8a9
a946dfc1
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
396 additions
and
152 deletions
+396
-152
include/nlohmann/detail/conversions/from_json.hpp
include/nlohmann/detail/conversions/from_json.hpp
+24
-24
include/nlohmann/detail/meta/type_traits.hpp
include/nlohmann/detail/meta/type_traits.hpp
+153
-52
single_include/nlohmann/json.hpp
single_include/nlohmann/json.hpp
+177
-76
test/src/unit-regression.cpp
test/src/unit-regression.cpp
+42
-0
No files found.
include/nlohmann/detail/conversions/from_json.hpp
View file @
9294e25c
...
...
@@ -84,13 +84,13 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
}
template
<
typename
BasicJsonType
,
typename
Co
mpa
tibleStringType
,
typename
BasicJsonType
,
typename
Co
nstruc
tibleStringType
,
enable_if_t
<
is_co
mpatible_string_type
<
BasicJsonType
,
Compa
tibleStringType
>
::
value
and
is_co
nstructible_string_type
<
BasicJsonType
,
Construc
tibleStringType
>
::
value
and
not
std
::
is_same
<
typename
BasicJsonType
::
string_t
,
Co
mpa
tibleStringType
>::
value
,
Co
nstruc
tibleStringType
>::
value
,
int
>
=
0
>
void
from_json
(
const
BasicJsonType
&
j
,
Co
mpa
tibleStringType
&
s
)
void
from_json
(
const
BasicJsonType
&
j
,
Co
nstruc
tibleStringType
&
s
)
{
if
(
JSON_UNLIKELY
(
not
j
.
is_string
()))
{
...
...
@@ -173,11 +173,11 @@ auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
}
}
template
<
typename
BasicJsonType
,
typename
Co
mpa
tibleArrayType
>
auto
from_json_array_impl
(
const
BasicJsonType
&
j
,
Co
mpa
tibleArrayType
&
arr
,
priority_tag
<
1
>
/*unused*/
)
template
<
typename
BasicJsonType
,
typename
Co
nstruc
tibleArrayType
>
auto
from_json_array_impl
(
const
BasicJsonType
&
j
,
Co
nstruc
tibleArrayType
&
arr
,
priority_tag
<
1
>
/*unused*/
)
->
decltype
(
arr
.
reserve
(
std
::
declval
<
typename
Co
mpa
tibleArrayType
::
size_type
>
()),
j
.
template
get
<
typename
Co
mpa
tibleArrayType
::
value_type
>(),
arr
.
reserve
(
std
::
declval
<
typename
Co
nstruc
tibleArrayType
::
size_type
>
()),
j
.
template
get
<
typename
Co
nstruc
tibleArrayType
::
value_type
>(),
void
())
{
using
std
::
end
;
...
...
@@ -188,12 +188,12 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
{
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
return
i
.
template
get
<
typename
Co
mpa
tibleArrayType
::
value_type
>();
return
i
.
template
get
<
typename
Co
nstruc
tibleArrayType
::
value_type
>();
});
}
template
<
typename
BasicJsonType
,
typename
Co
mpa
tibleArrayType
>
void
from_json_array_impl
(
const
BasicJsonType
&
j
,
Co
mpa
tibleArrayType
&
arr
,
template
<
typename
BasicJsonType
,
typename
Co
nstruc
tibleArrayType
>
void
from_json_array_impl
(
const
BasicJsonType
&
j
,
Co
nstruc
tibleArrayType
&
arr
,
priority_tag
<
0
>
/*unused*/
)
{
using
std
::
end
;
...
...
@@ -204,21 +204,21 @@ void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr,
{
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
return
i
.
template
get
<
typename
Co
mpa
tibleArrayType
::
value_type
>();
return
i
.
template
get
<
typename
Co
nstruc
tibleArrayType
::
value_type
>();
});
}
template
<
typename
BasicJsonType
,
typename
Co
mpa
tibleArrayType
,
template
<
typename
BasicJsonType
,
typename
Co
nstruc
tibleArrayType
,
enable_if_t
<
is_co
mpatible_array_type
<
BasicJsonType
,
Compa
tibleArrayType
>
::
value
and
not
is_co
mpatible_object_type
<
BasicJsonType
,
Compa
tibleArrayType
>::
value
and
not
is_co
mpatible_string_type
<
BasicJsonType
,
Compa
tibleArrayType
>::
value
and
not
is_basic_json
<
Co
mpa
tibleArrayType
>::
value
,
is_co
nstructible_array_type
<
BasicJsonType
,
Construc
tibleArrayType
>
::
value
and
not
is_co
nstructible_object_type
<
BasicJsonType
,
Construc
tibleArrayType
>::
value
and
not
is_co
nstructible_string_type
<
BasicJsonType
,
Construc
tibleArrayType
>::
value
and
not
is_basic_json
<
Co
nstruc
tibleArrayType
>::
value
,
int
>
=
0
>
auto
from_json
(
const
BasicJsonType
&
j
,
Co
mpa
tibleArrayType
&
arr
)
auto
from_json
(
const
BasicJsonType
&
j
,
Co
nstruc
tibleArrayType
&
arr
)
->
decltype
(
from_json_array_impl
(
j
,
arr
,
priority_tag
<
3
>
{}),
j
.
template
get
<
typename
Co
mpa
tibleArrayType
::
value_type
>(),
j
.
template
get
<
typename
Co
nstruc
tibleArrayType
::
value_type
>(),
void
())
{
if
(
JSON_UNLIKELY
(
not
j
.
is_array
()))
...
...
@@ -230,9 +230,9 @@ void())
from_json_array_impl
(
j
,
arr
,
priority_tag
<
3
>
{});
}
template
<
typename
BasicJsonType
,
typename
Co
mpa
tibleObjectType
,
enable_if_t
<
is_co
mpatible_object_type
<
BasicJsonType
,
Compa
tibleObjectType
>
::
value
,
int
>
=
0
>
void
from_json
(
const
BasicJsonType
&
j
,
Co
mpa
tibleObjectType
&
obj
)
template
<
typename
BasicJsonType
,
typename
Co
nstruc
tibleObjectType
,
enable_if_t
<
is_co
nstructible_object_type
<
BasicJsonType
,
Construc
tibleObjectType
>
::
value
,
int
>
=
0
>
void
from_json
(
const
BasicJsonType
&
j
,
Co
nstruc
tibleObjectType
&
obj
)
{
if
(
JSON_UNLIKELY
(
not
j
.
is_object
()))
{
...
...
@@ -240,13 +240,13 @@ void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
}
auto
inner_object
=
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
object_t
*
>();
using
value_type
=
typename
Co
mpa
tibleObjectType
::
value_type
;
using
value_type
=
typename
Co
nstruc
tibleObjectType
::
value_type
;
std
::
transform
(
inner_object
->
begin
(),
inner_object
->
end
(),
std
::
inserter
(
obj
,
obj
.
begin
()),
[](
typename
BasicJsonType
::
object_t
::
value_type
const
&
p
)
{
return
value_type
(
p
.
first
,
p
.
second
.
template
get
<
typename
Co
mpa
tibleObjectType
::
mapped_type
>());
return
value_type
(
p
.
first
,
p
.
second
.
template
get
<
typename
Co
nstruc
tibleObjectType
::
mapped_type
>());
});
}
...
...
include/nlohmann/detail/meta/type_traits.hpp
View file @
9294e25c
...
...
@@ -26,6 +26,15 @@ namespace detail
// helpers //
/////////////
// Note to maintainers:
//
// Every trait in this file expects a non CV-qualified type.
// The only exceptions are in the 'aliases for detected' section
// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
//
// In this case, T has to be properly CV-qualified to constraint the function arguments
// (e.g. to_json(BasicJsonType&, const T&))
template
<
typename
>
struct
is_basic_json
:
std
::
false_type
{};
NLOHMANN_BASIC_JSON_TPL_DECLARATION
...
...
@@ -68,6 +77,52 @@ using from_json_function = decltype(T::from_json(std::declval<Args>()...));
template
<
typename
T
,
typename
U
>
using
get_template_function
=
decltype
(
std
::
declval
<
T
>
().
template
get
<
U
>());
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
template
<
typename
BasicJsonType
,
typename
T
,
typename
=
void
>
struct
has_from_json
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_from_json
<
BasicJsonType
,
T
,
enable_if_t
<
not
is_basic_json
<
T
>::
value
>>
{
using
serializer
=
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>;
static
constexpr
bool
value
=
is_detected_exact
<
void
,
from_json_function
,
serializer
,
const
BasicJsonType
&
,
T
&>::
value
;
};
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// this overload is used for non-default-constructible user-defined-types
template
<
typename
BasicJsonType
,
typename
T
,
typename
=
void
>
struct
has_non_default_from_json
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_non_default_from_json
<
BasicJsonType
,
T
,
enable_if_t
<
not
is_basic_json
<
T
>::
value
>>
{
using
serializer
=
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>;
static
constexpr
bool
value
=
is_detected_exact
<
T
,
from_json_function
,
serializer
,
const
BasicJsonType
&>::
value
;
};
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
template
<
typename
BasicJsonType
,
typename
T
,
typename
=
void
>
struct
has_to_json
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_to_json
<
BasicJsonType
,
T
,
enable_if_t
<
not
is_basic_json
<
T
>::
value
>>
{
using
serializer
=
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>;
static
constexpr
bool
value
=
is_detected_exact
<
void
,
to_json_function
,
serializer
,
BasicJsonType
&
,
T
>::
value
;
};
///////////////////
// is_ functions //
///////////////////
...
...
@@ -123,6 +178,35 @@ template <typename BasicJsonType, typename CompatibleObjectType>
struct
is_compatible_object_type
:
is_compatible_object_type_impl
<
BasicJsonType
,
CompatibleObjectType
>
{};
template
<
typename
BasicJsonType
,
typename
ConstructibleObjectType
,
typename
=
void
>
struct
is_constructible_object_type_impl
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
ConstructibleObjectType
>
struct
is_constructible_object_type_impl
<
BasicJsonType
,
ConstructibleObjectType
,
enable_if_t
<
is_detected
<
mapped_type_t
,
ConstructibleObjectType
>::
value
and
is_detected
<
key_type_t
,
ConstructibleObjectType
>::
value
>>
{
using
object_t
=
typename
BasicJsonType
::
object_t
;
static
constexpr
bool
value
=
std
::
is_constructible
<
typename
ConstructibleObjectType
::
key_type
,
typename
object_t
::
key_type
>::
value
and
std
::
is_same
<
typename
object_t
::
mapped_type
,
typename
ConstructibleObjectType
::
mapped_type
>::
value
or
(
has_from_json
<
BasicJsonType
,
typename
ConstructibleObjectType
::
mapped_type
>::
value
or
has_non_default_from_json
<
BasicJsonType
,
typename
ConstructibleObjectType
::
mapped_type
>::
value
);
};
template
<
typename
BasicJsonType
,
typename
ConstructibleObjectType
>
struct
is_constructible_object_type
:
is_constructible_object_type_impl
<
BasicJsonType
,
ConstructibleObjectType
>
{};
template
<
typename
BasicJsonType
,
typename
CompatibleStringType
,
typename
=
void
>
struct
is_compatible_string_type_impl
:
std
::
false_type
{};
...
...
@@ -137,9 +221,28 @@ struct is_compatible_string_type_impl <
std
::
is_constructible
<
typename
BasicJsonType
::
string_t
,
CompatibleStringType
>::
value
;
};
template
<
typename
BasicJsonType
,
typename
Co
mpa
tibleStringType
>
template
<
typename
BasicJsonType
,
typename
Co
nstru
tibleStringType
>
struct
is_compatible_string_type
:
is_compatible_string_type_impl
<
BasicJsonType
,
CompatibleStringType
>
{};
:
is_compatible_string_type_impl
<
BasicJsonType
,
ConstrutibleStringType
>
{};
template
<
typename
BasicJsonType
,
typename
ConstrutibleStringType
,
typename
=
void
>
struct
is_constructible_string_type_impl
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
ConstrutibleStringType
>
struct
is_constructible_string_type_impl
<
BasicJsonType
,
ConstrutibleStringType
,
enable_if_t
<
is_detected_exact
<
typename
BasicJsonType
::
string_t
::
value_type
,
value_type_t
,
ConstrutibleStringType
>::
value
>>
{
static
constexpr
auto
value
=
std
::
is_constructible
<
ConstrutibleStringType
,
typename
BasicJsonType
::
string_t
>::
value
;
};
template
<
typename
BasicJsonType
,
typename
ConstrutibleStringType
>
struct
is_constructible_string_type
:
is_constructible_string_type_impl
<
BasicJsonType
,
ConstrutibleStringType
>
{};
template
<
typename
BasicJsonType
,
typename
CompatibleArrayType
,
typename
=
void
>
struct
is_compatible_array_type_impl
:
std
::
false_type
{};
...
...
@@ -148,18 +251,61 @@ template <typename BasicJsonType, typename CompatibleArrayType>
struct
is_compatible_array_type_impl
<
BasicJsonType
,
CompatibleArrayType
,
enable_if_t
<
is_detected
<
value_type_t
,
CompatibleArrayType
>::
value
and
is_detected
<
iterator_t
,
CompatibleArrayType
>::
value
>>
is_detected
<
iterator_t
,
CompatibleArrayType
>::
value
and
// This is needed because json_reverse_iterator has a ::iterator type...
// Therefore it is detected as a CompatibleArrayType.
// The real fix would be to have an Iterable concept.
not
is_iterator_traits
<
std
::
iterator_traits
<
CompatibleArrayType
>>::
value
>>
{
// This is needed because json_reverse_iterator has a ::iterator type...
// Therefore it is detected as a CompatibleArrayType.
// The real fix would be to have an Iterable concept.
static
constexpr
bool
value
=
not
is_iterator_traits
<
std
::
iterator_traits
<
CompatibleArrayType
>>::
value
;
static
constexpr
bool
value
=
std
::
is_constructible
<
BasicJsonType
,
typename
CompatibleArrayType
::
value_type
>::
value
;
};
template
<
typename
BasicJsonType
,
typename
CompatibleArrayType
>
struct
is_compatible_array_type
:
is_compatible_array_type_impl
<
BasicJsonType
,
CompatibleArrayType
>
{};
template
<
typename
BasicJsonType
,
typename
ConstructibleArrayType
,
typename
=
void
>
struct
is_constructible_array_type_impl
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
ConstructibleArrayType
>
struct
is_constructible_array_type_impl
<
BasicJsonType
,
ConstructibleArrayType
,
enable_if_t
<
std
::
is_same
<
ConstructibleArrayType
,
typename
BasicJsonType
::
value_type
>::
value
>>
:
std
::
true_type
{};
template
<
typename
BasicJsonType
,
typename
ConstructibleArrayType
>
struct
is_constructible_array_type_impl
<
BasicJsonType
,
ConstructibleArrayType
,
enable_if_t
<
not
std
::
is_same
<
ConstructibleArrayType
,
typename
BasicJsonType
::
value_type
>::
value
and
is_detected
<
value_type_t
,
ConstructibleArrayType
>::
value
and
is_detected
<
iterator_t
,
ConstructibleArrayType
>::
value
and
is_complete_type
<
detected_t
<
value_type_t
,
ConstructibleArrayType
>>::
value
>>
{
static
constexpr
bool
value
=
// This is needed because json_reverse_iterator has a ::iterator type,
// furthermore, std::back_insert_iterator (and other iterators) have a base class `iterator`...
// Therefore it is detected as a ConstructibleArrayType.
// The real fix would be to have an Iterable concept.
not
is_iterator_traits
<
std
::
iterator_traits
<
ConstructibleArrayType
>>::
value
and
(
std
::
is_same
<
typename
ConstructibleArrayType
::
value_type
,
typename
BasicJsonType
::
array_t
::
value_type
>::
value
or
has_from_json
<
BasicJsonType
,
typename
ConstructibleArrayType
::
value_type
>::
value
or
has_non_default_from_json
<
BasicJsonType
,
typename
ConstructibleArrayType
::
value_type
>::
value
);
};
template
<
typename
BasicJsonType
,
typename
ConstructibleArrayType
>
struct
is_constructible_array_type
:
is_constructible_array_type_impl
<
BasicJsonType
,
ConstructibleArrayType
>
{};
template
<
typename
RealIntegerType
,
typename
CompatibleNumberIntegerType
,
typename
=
void
>
struct
is_compatible_integer_type_impl
:
std
::
false_type
{};
...
...
@@ -187,51 +333,6 @@ struct is_compatible_integer_type
:
is_compatible_integer_type_impl
<
RealIntegerType
,
CompatibleNumberIntegerType
>
{};
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
template
<
typename
BasicJsonType
,
typename
T
,
typename
=
void
>
struct
has_from_json
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_from_json
<
BasicJsonType
,
T
,
enable_if_t
<
not
is_basic_json
<
T
>::
value
>>
{
using
serializer
=
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>;
static
constexpr
bool
value
=
is_detected_exact
<
void
,
from_json_function
,
serializer
,
const
BasicJsonType
&
,
T
&>::
value
;
};
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// this overload is used for non-default-constructible user-defined-types
template
<
typename
BasicJsonType
,
typename
T
,
typename
=
void
>
struct
has_non_default_from_json
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_non_default_from_json
<
BasicJsonType
,
T
,
enable_if_t
<
not
is_basic_json
<
T
>::
value
>>
{
using
serializer
=
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>;
static
constexpr
bool
value
=
is_detected_exact
<
T
,
from_json_function
,
serializer
,
const
BasicJsonType
&>::
value
;
};
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
template
<
typename
BasicJsonType
,
typename
T
,
typename
=
void
>
struct
has_to_json
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_to_json
<
BasicJsonType
,
T
,
enable_if_t
<
not
is_basic_json
<
T
>::
value
>>
{
using
serializer
=
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>;
static
constexpr
bool
value
=
is_detected_exact
<
void
,
to_json_function
,
serializer
,
BasicJsonType
&
,
T
>::
value
;
};
template
<
typename
BasicJsonType
,
typename
CompatibleType
,
typename
=
void
>
struct
is_compatible_type_impl
:
std
::
false_type
{};
...
...
single_include/nlohmann/json.hpp
View file @
9294e25c
...
...
@@ -386,6 +386,15 @@ namespace detail
// helpers //
/////////////
// Note to maintainers:
//
// Every trait in this file expects a non CV-qualified type.
// The only exceptions are in the 'aliases for detected' section
// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
//
// In this case, T has to be properly CV-qualified to constraint the function arguments
// (e.g. to_json(BasicJsonType&, const T&))
template
<
typename
>
struct
is_basic_json
:
std
::
false_type
{};
NLOHMANN_BASIC_JSON_TPL_DECLARATION
...
...
@@ -428,6 +437,52 @@ using from_json_function = decltype(T::from_json(std::declval<Args>()...));
template
<
typename
T
,
typename
U
>
using
get_template_function
=
decltype
(
std
::
declval
<
T
>
().
template
get
<
U
>());
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
template
<
typename
BasicJsonType
,
typename
T
,
typename
=
void
>
struct
has_from_json
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_from_json
<
BasicJsonType
,
T
,
enable_if_t
<
not
is_basic_json
<
T
>::
value
>>
{
using
serializer
=
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>;
static
constexpr
bool
value
=
is_detected_exact
<
void
,
from_json_function
,
serializer
,
const
BasicJsonType
&
,
T
&>::
value
;
};
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// this overload is used for non-default-constructible user-defined-types
template
<
typename
BasicJsonType
,
typename
T
,
typename
=
void
>
struct
has_non_default_from_json
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_non_default_from_json
<
BasicJsonType
,
T
,
enable_if_t
<
not
is_basic_json
<
T
>::
value
>>
{
using
serializer
=
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>;
static
constexpr
bool
value
=
is_detected_exact
<
T
,
from_json_function
,
serializer
,
const
BasicJsonType
&>::
value
;
};
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
template
<
typename
BasicJsonType
,
typename
T
,
typename
=
void
>
struct
has_to_json
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_to_json
<
BasicJsonType
,
T
,
enable_if_t
<
not
is_basic_json
<
T
>::
value
>>
{
using
serializer
=
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>;
static
constexpr
bool
value
=
is_detected_exact
<
void
,
to_json_function
,
serializer
,
BasicJsonType
&
,
T
>::
value
;
};
///////////////////
// is_ functions //
///////////////////
...
...
@@ -483,6 +538,35 @@ template <typename BasicJsonType, typename CompatibleObjectType>
struct
is_compatible_object_type
:
is_compatible_object_type_impl
<
BasicJsonType
,
CompatibleObjectType
>
{};
template
<
typename
BasicJsonType
,
typename
ConstructibleObjectType
,
typename
=
void
>
struct
is_constructible_object_type_impl
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
ConstructibleObjectType
>
struct
is_constructible_object_type_impl
<
BasicJsonType
,
ConstructibleObjectType
,
enable_if_t
<
is_detected
<
mapped_type_t
,
ConstructibleObjectType
>::
value
and
is_detected
<
key_type_t
,
ConstructibleObjectType
>::
value
>>
{
using
object_t
=
typename
BasicJsonType
::
object_t
;
static
constexpr
bool
value
=
std
::
is_constructible
<
typename
ConstructibleObjectType
::
key_type
,
typename
object_t
::
key_type
>::
value
and
std
::
is_same
<
typename
object_t
::
mapped_type
,
typename
ConstructibleObjectType
::
mapped_type
>::
value
or
(
has_from_json
<
BasicJsonType
,
typename
ConstructibleObjectType
::
mapped_type
>::
value
or
has_non_default_from_json
<
BasicJsonType
,
typename
ConstructibleObjectType
::
mapped_type
>::
value
);
};
template
<
typename
BasicJsonType
,
typename
ConstructibleObjectType
>
struct
is_constructible_object_type
:
is_constructible_object_type_impl
<
BasicJsonType
,
ConstructibleObjectType
>
{};
template
<
typename
BasicJsonType
,
typename
CompatibleStringType
,
typename
=
void
>
struct
is_compatible_string_type_impl
:
std
::
false_type
{};
...
...
@@ -497,9 +581,28 @@ struct is_compatible_string_type_impl <
std
::
is_constructible
<
typename
BasicJsonType
::
string_t
,
CompatibleStringType
>::
value
;
};
template
<
typename
BasicJsonType
,
typename
Co
mpa
tibleStringType
>
template
<
typename
BasicJsonType
,
typename
Co
nstru
tibleStringType
>
struct
is_compatible_string_type
:
is_compatible_string_type_impl
<
BasicJsonType
,
CompatibleStringType
>
{};
:
is_compatible_string_type_impl
<
BasicJsonType
,
ConstrutibleStringType
>
{};
template
<
typename
BasicJsonType
,
typename
ConstrutibleStringType
,
typename
=
void
>
struct
is_constructible_string_type_impl
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
ConstrutibleStringType
>
struct
is_constructible_string_type_impl
<
BasicJsonType
,
ConstrutibleStringType
,
enable_if_t
<
is_detected_exact
<
typename
BasicJsonType
::
string_t
::
value_type
,
value_type_t
,
ConstrutibleStringType
>::
value
>>
{
static
constexpr
auto
value
=
std
::
is_constructible
<
ConstrutibleStringType
,
typename
BasicJsonType
::
string_t
>::
value
;
};
template
<
typename
BasicJsonType
,
typename
ConstrutibleStringType
>
struct
is_constructible_string_type
:
is_constructible_string_type_impl
<
BasicJsonType
,
ConstrutibleStringType
>
{};
template
<
typename
BasicJsonType
,
typename
CompatibleArrayType
,
typename
=
void
>
struct
is_compatible_array_type_impl
:
std
::
false_type
{};
...
...
@@ -508,18 +611,61 @@ template <typename BasicJsonType, typename CompatibleArrayType>
struct
is_compatible_array_type_impl
<
BasicJsonType
,
CompatibleArrayType
,
enable_if_t
<
is_detected
<
value_type_t
,
CompatibleArrayType
>::
value
and
is_detected
<
iterator_t
,
CompatibleArrayType
>::
value
>>
is_detected
<
iterator_t
,
CompatibleArrayType
>::
value
and
// This is needed because json_reverse_iterator has a ::iterator type...
// Therefore it is detected as a CompatibleArrayType.
// The real fix would be to have an Iterable concept.
not
is_iterator_traits
<
std
::
iterator_traits
<
CompatibleArrayType
>>::
value
>>
{
// This is needed because json_reverse_iterator has a ::iterator type...
// Therefore it is detected as a CompatibleArrayType.
// The real fix would be to have an Iterable concept.
static
constexpr
bool
value
=
not
is_iterator_traits
<
std
::
iterator_traits
<
CompatibleArrayType
>>::
value
;
static
constexpr
bool
value
=
std
::
is_constructible
<
BasicJsonType
,
typename
CompatibleArrayType
::
value_type
>::
value
;
};
template
<
typename
BasicJsonType
,
typename
CompatibleArrayType
>
struct
is_compatible_array_type
:
is_compatible_array_type_impl
<
BasicJsonType
,
CompatibleArrayType
>
{};
template
<
typename
BasicJsonType
,
typename
ConstructibleArrayType
,
typename
=
void
>
struct
is_constructible_array_type_impl
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
ConstructibleArrayType
>
struct
is_constructible_array_type_impl
<
BasicJsonType
,
ConstructibleArrayType
,
enable_if_t
<
std
::
is_same
<
ConstructibleArrayType
,
typename
BasicJsonType
::
value_type
>::
value
>>
:
std
::
true_type
{};
template
<
typename
BasicJsonType
,
typename
ConstructibleArrayType
>
struct
is_constructible_array_type_impl
<
BasicJsonType
,
ConstructibleArrayType
,
enable_if_t
<
not
std
::
is_same
<
ConstructibleArrayType
,
typename
BasicJsonType
::
value_type
>::
value
and
is_detected
<
value_type_t
,
ConstructibleArrayType
>::
value
and
is_detected
<
iterator_t
,
ConstructibleArrayType
>::
value
and
is_complete_type
<
detected_t
<
value_type_t
,
ConstructibleArrayType
>>::
value
>>
{
static
constexpr
bool
value
=
// This is needed because json_reverse_iterator has a ::iterator type,
// furthermore, std::back_insert_iterator (and other iterators) have a base class `iterator`...
// Therefore it is detected as a ConstructibleArrayType.
// The real fix would be to have an Iterable concept.
not
is_iterator_traits
<
std
::
iterator_traits
<
ConstructibleArrayType
>>::
value
and
(
std
::
is_same
<
typename
ConstructibleArrayType
::
value_type
,
typename
BasicJsonType
::
array_t
::
value_type
>::
value
or
has_from_json
<
BasicJsonType
,
typename
ConstructibleArrayType
::
value_type
>::
value
or
has_non_default_from_json
<
BasicJsonType
,
typename
ConstructibleArrayType
::
value_type
>::
value
);
};
template
<
typename
BasicJsonType
,
typename
ConstructibleArrayType
>
struct
is_constructible_array_type
:
is_constructible_array_type_impl
<
BasicJsonType
,
ConstructibleArrayType
>
{};
template
<
typename
RealIntegerType
,
typename
CompatibleNumberIntegerType
,
typename
=
void
>
struct
is_compatible_integer_type_impl
:
std
::
false_type
{};
...
...
@@ -547,51 +693,6 @@ struct is_compatible_integer_type
:
is_compatible_integer_type_impl
<
RealIntegerType
,
CompatibleNumberIntegerType
>
{};
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
template
<
typename
BasicJsonType
,
typename
T
,
typename
=
void
>
struct
has_from_json
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_from_json
<
BasicJsonType
,
T
,
enable_if_t
<
not
is_basic_json
<
T
>::
value
>>
{
using
serializer
=
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>;
static
constexpr
bool
value
=
is_detected_exact
<
void
,
from_json_function
,
serializer
,
const
BasicJsonType
&
,
T
&>::
value
;
};
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// this overload is used for non-default-constructible user-defined-types
template
<
typename
BasicJsonType
,
typename
T
,
typename
=
void
>
struct
has_non_default_from_json
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_non_default_from_json
<
BasicJsonType
,
T
,
enable_if_t
<
not
is_basic_json
<
T
>::
value
>>
{
using
serializer
=
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>;
static
constexpr
bool
value
=
is_detected_exact
<
T
,
from_json_function
,
serializer
,
const
BasicJsonType
&>::
value
;
};
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
template
<
typename
BasicJsonType
,
typename
T
,
typename
=
void
>
struct
has_to_json
:
std
::
false_type
{};
template
<
typename
BasicJsonType
,
typename
T
>
struct
has_to_json
<
BasicJsonType
,
T
,
enable_if_t
<
not
is_basic_json
<
T
>::
value
>>
{
using
serializer
=
typename
BasicJsonType
::
template
json_serializer
<
T
,
void
>;
static
constexpr
bool
value
=
is_detected_exact
<
void
,
to_json_function
,
serializer
,
BasicJsonType
&
,
T
>::
value
;
};
template
<
typename
BasicJsonType
,
typename
CompatibleType
,
typename
=
void
>
struct
is_compatible_type_impl
:
std
::
false_type
{};
...
...
@@ -1156,13 +1257,13 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
}
template
<
typename
BasicJsonType
,
typename
Co
mpa
tibleStringType
,
typename
BasicJsonType
,
typename
Co
nstruc
tibleStringType
,
enable_if_t
<
is_co
mpatible_string_type
<
BasicJsonType
,
Compa
tibleStringType
>
::
value
and
is_co
nstructible_string_type
<
BasicJsonType
,
Construc
tibleStringType
>
::
value
and
not
std
::
is_same
<
typename
BasicJsonType
::
string_t
,
Co
mpa
tibleStringType
>::
value
,
Co
nstruc
tibleStringType
>::
value
,
int
>
=
0
>
void
from_json
(
const
BasicJsonType
&
j
,
Co
mpa
tibleStringType
&
s
)
void
from_json
(
const
BasicJsonType
&
j
,
Co
nstruc
tibleStringType
&
s
)
{
if
(
JSON_UNLIKELY
(
not
j
.
is_string
()))
{
...
...
@@ -1245,11 +1346,11 @@ auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
}
}
template
<
typename
BasicJsonType
,
typename
Co
mpa
tibleArrayType
>
auto
from_json_array_impl
(
const
BasicJsonType
&
j
,
Co
mpa
tibleArrayType
&
arr
,
priority_tag
<
1
>
/*unused*/
)
template
<
typename
BasicJsonType
,
typename
Co
nstruc
tibleArrayType
>
auto
from_json_array_impl
(
const
BasicJsonType
&
j
,
Co
nstruc
tibleArrayType
&
arr
,
priority_tag
<
1
>
/*unused*/
)
->
decltype
(
arr
.
reserve
(
std
::
declval
<
typename
Co
mpa
tibleArrayType
::
size_type
>
()),
j
.
template
get
<
typename
Co
mpa
tibleArrayType
::
value_type
>(),
arr
.
reserve
(
std
::
declval
<
typename
Co
nstruc
tibleArrayType
::
size_type
>
()),
j
.
template
get
<
typename
Co
nstruc
tibleArrayType
::
value_type
>(),
void
())
{
using
std
::
end
;
...
...
@@ -1260,12 +1361,12 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
{
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
return
i
.
template
get
<
typename
Co
mpa
tibleArrayType
::
value_type
>();
return
i
.
template
get
<
typename
Co
nstruc
tibleArrayType
::
value_type
>();
});
}
template
<
typename
BasicJsonType
,
typename
Co
mpa
tibleArrayType
>
void
from_json_array_impl
(
const
BasicJsonType
&
j
,
Co
mpa
tibleArrayType
&
arr
,
template
<
typename
BasicJsonType
,
typename
Co
nstruc
tibleArrayType
>
void
from_json_array_impl
(
const
BasicJsonType
&
j
,
Co
nstruc
tibleArrayType
&
arr
,
priority_tag
<
0
>
/*unused*/
)
{
using
std
::
end
;
...
...
@@ -1276,21 +1377,21 @@ void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr,
{
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
return
i
.
template
get
<
typename
Co
mpa
tibleArrayType
::
value_type
>();
return
i
.
template
get
<
typename
Co
nstruc
tibleArrayType
::
value_type
>();
});
}
template
<
typename
BasicJsonType
,
typename
Co
mpa
tibleArrayType
,
template
<
typename
BasicJsonType
,
typename
Co
nstruc
tibleArrayType
,
enable_if_t
<
is_co
mpatible_array_type
<
BasicJsonType
,
Compa
tibleArrayType
>
::
value
and
not
is_co
mpatible_object_type
<
BasicJsonType
,
Compa
tibleArrayType
>::
value
and
not
is_co
mpatible_string_type
<
BasicJsonType
,
Compa
tibleArrayType
>::
value
and
not
is_basic_json
<
Co
mpa
tibleArrayType
>::
value
,
is_co
nstructible_array_type
<
BasicJsonType
,
Construc
tibleArrayType
>
::
value
and
not
is_co
nstructible_object_type
<
BasicJsonType
,
Construc
tibleArrayType
>::
value
and
not
is_co
nstructible_string_type
<
BasicJsonType
,
Construc
tibleArrayType
>::
value
and
not
is_basic_json
<
Co
nstruc
tibleArrayType
>::
value
,
int
>
=
0
>
auto
from_json
(
const
BasicJsonType
&
j
,
Co
mpa
tibleArrayType
&
arr
)
auto
from_json
(
const
BasicJsonType
&
j
,
Co
nstruc
tibleArrayType
&
arr
)
->
decltype
(
from_json_array_impl
(
j
,
arr
,
priority_tag
<
3
>
{}),
j
.
template
get
<
typename
Co
mpa
tibleArrayType
::
value_type
>(),
j
.
template
get
<
typename
Co
nstruc
tibleArrayType
::
value_type
>(),
void
())
{
if
(
JSON_UNLIKELY
(
not
j
.
is_array
()))
...
...
@@ -1302,9 +1403,9 @@ void())
from_json_array_impl
(
j
,
arr
,
priority_tag
<
3
>
{});
}
template
<
typename
BasicJsonType
,
typename
Co
mpa
tibleObjectType
,
enable_if_t
<
is_co
mpatible_object_type
<
BasicJsonType
,
Compa
tibleObjectType
>
::
value
,
int
>
=
0
>
void
from_json
(
const
BasicJsonType
&
j
,
Co
mpa
tibleObjectType
&
obj
)
template
<
typename
BasicJsonType
,
typename
Co
nstruc
tibleObjectType
,
enable_if_t
<
is_co
nstructible_object_type
<
BasicJsonType
,
Construc
tibleObjectType
>
::
value
,
int
>
=
0
>
void
from_json
(
const
BasicJsonType
&
j
,
Co
nstruc
tibleObjectType
&
obj
)
{
if
(
JSON_UNLIKELY
(
not
j
.
is_object
()))
{
...
...
@@ -1312,13 +1413,13 @@ void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
}
auto
inner_object
=
j
.
template
get_ptr
<
const
typename
BasicJsonType
::
object_t
*
>();
using
value_type
=
typename
Co
mpa
tibleObjectType
::
value_type
;
using
value_type
=
typename
Co
nstruc
tibleObjectType
::
value_type
;
std
::
transform
(
inner_object
->
begin
(),
inner_object
->
end
(),
std
::
inserter
(
obj
,
obj
.
begin
()),
[](
typename
BasicJsonType
::
object_t
::
value_type
const
&
p
)
{
return
value_type
(
p
.
first
,
p
.
second
.
template
get
<
typename
Co
mpa
tibleObjectType
::
mapped_type
>());
return
value_type
(
p
.
first
,
p
.
second
.
template
get
<
typename
Co
nstruc
tibleObjectType
::
mapped_type
>());
});
}
...
...
test/src/unit-regression.cpp
View file @
9294e25c
...
...
@@ -121,6 +121,28 @@ struct nocopy
j
=
{{
"val"
,
n
.
val
}};
}
};
struct
Data
{
std
::
string
a
;
std
::
string
b
;
};
void
from_json
(
const
json
&
j
,
Data
&
data
)
{
j
[
"a"
].
get_to
(
data
.
a
);
j
[
"b"
].
get_to
(
data
.
b
);
}
bool
operator
==
(
Data
const
&
lhs
,
Data
const
&
rhs
)
{
return
lhs
.
a
==
rhs
.
a
&&
lhs
.
b
==
rhs
.
b
;
}
bool
operator
!=
(
Data
const
&
lhs
,
Data
const
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
}
/////////////////////////////////////////////////////////////////////
...
...
@@ -1665,4 +1687,24 @@ TEST_CASE("regression tests")
not
std
::
is_constructible
<
json
,
std
::
variant
<
int
,
float
>>::
value
,
""
);
}
#endif
SECTION
(
"issue #1299 - compile error in from_json converting to container "
"with std::pair"
)
{
json
j
=
{
{
"1"
,
{{
"a"
,
"testa_1"
},
{
"b"
,
"testb_1"
}}},
{
"2"
,
{{
"a"
,
"testa_2"
},
{
"b"
,
"testb_2"
}}},
{
"3"
,
{{
"a"
,
"testa_3"
},
{
"b"
,
"testb_3"
}}},
};
std
::
map
<
std
::
string
,
Data
>
expected
{
{
"1"
,
{
"testa_1"
,
"testb_1"
}},
{
"2"
,
{
"testa_2"
,
"testb_2"
}},
{
"3"
,
{
"testa_3"
,
"testb_3"
}},
};
const
auto
data
=
j
.
get
<
decltype
(
expected
)
>
();
CHECK
(
expected
==
data
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment