mirror of
https://github.com/nlohmann/json.git
synced 2026-10-26 15:58:55 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93ccdc2738 | ||
|
|
46b6daec9f |
No files matched your search
@@ -19,16 +19,19 @@ For the types below, the conversion works directly on the flat index -- no `Basi
|
|||||||
document's own buffer of decoded strings (see [`get_string()`](get_string.md))
|
document's own buffer of decoded strings (see [`get_string()`](get_string.md))
|
||||||
- `BasicJsonType` -- equivalent to [`materialize()`](materialize.md)
|
- `BasicJsonType` -- equivalent to [`materialize()`](materialize.md)
|
||||||
- `basic_json_view` -- returns `#!cpp *this`
|
- `basic_json_view` -- returns `#!cpp *this`
|
||||||
- `#!cpp std::vector<U, A>` -- from an array, element by element, each converted with `#!cpp get<U>()`; `#!cpp
|
- `#!cpp std::vector<U, A>` of the types above -- from an array, element by element, each converted with
|
||||||
std::vector<basic_json_view>` keeps a view of every element instead of a value
|
`#!cpp get<U>()`; `#!cpp std::vector<basic_json_view>` keeps a view of every element instead of a value
|
||||||
- `#!cpp std::map<K, V, C, A>` and `#!cpp std::unordered_map<K, V, H, E, A>`, if `K` is constructible from a `#!cpp
|
- `#!cpp std::map<K, basic_json_view, C, A>` and `#!cpp std::unordered_map<K, basic_json_view, H, E, A>`, if `K` is
|
||||||
(const char*, std::size_t)` pair -- from an object, member by member, each value converted with `#!cpp get<V>()`; with a repeated
|
constructible from a `#!cpp (const char*, std::size_t)` pair -- views of the members of an object; with a repeated
|
||||||
key, the *last* value is kept, as [`BasicJsonType::parse()`](../basic_json/parse.md) (and
|
key, the view of the *last* member is kept, as [`BasicJsonType::parse()`](../basic_json/parse.md) keeps its value
|
||||||
[`materialize()`](materialize.md)) does; `#!cpp std::map<std::string, basic_json_view>` keeps views of the members
|
|
||||||
instead of values
|
|
||||||
|
|
||||||
A default-constructible `T` whose `from_json()` accepts views reads the view directly as well, member by member, without
|
A default-constructible `T` whose `from_json()` accepts views reads the view directly as well, without building a
|
||||||
building a `BasicJsonType` value. This covers the types of the
|
`BasicJsonType` value. This covers the library's own conversions of the standard library types -- all other
|
||||||
|
`#!cpp std::vector`s, `#!cpp std::map`/`#!cpp std::unordered_map` (also with other key types), `#!cpp std::list`,
|
||||||
|
`#!cpp std::deque`, `#!cpp std::set`, `#!cpp std::forward_list`, `#!cpp std::valarray`, `#!cpp std::array`, C arrays,
|
||||||
|
`#!cpp std::pair`, `#!cpp std::tuple`, `#!cpp std::optional`, enumerations, `#!cpp std::filesystem::path`, ... --
|
||||||
|
which give the same values as `#!cpp materialize().get<T>()` (from an object, a repeated key keeps the *last* value,
|
||||||
|
as [`BasicJsonType::parse()`](../basic_json/parse.md) does), as well as the types of the
|
||||||
[`NLOHMANN_DEFINE_TYPE_*`](../macros/nlohmann_define_type_intrusive.md) and
|
[`NLOHMANN_DEFINE_TYPE_*`](../macros/nlohmann_define_type_intrusive.md) and
|
||||||
[`NLOHMANN_DEFINE_DERIVED_TYPE_*`](../macros/nlohmann_define_derived_type.md) macros and the enumerations of
|
[`NLOHMANN_DEFINE_DERIVED_TYPE_*`](../macros/nlohmann_define_derived_type.md) macros and the enumerations of
|
||||||
[`NLOHMANN_JSON_SERIALIZE_ENUM`](../macros/nlohmann_json_serialize_enum.md), and any `from_json()` constrained to
|
[`NLOHMANN_JSON_SERIALIZE_ENUM`](../macros/nlohmann_json_serialize_enum.md), and any `from_json()` constrained to
|
||||||
@@ -44,8 +47,8 @@ T&)` of [arbitrary type conversions](../../features/arbitrary_types.md), is not
|
|||||||
keeps it: for `#!cpp {"x":1,"x":2}`, `#!cpp get<point>()` reads `#!cpp x == 1`. See
|
keeps it: for `#!cpp {"x":1,"x":2}`, `#!cpp get<point>()` reads `#!cpp x == 1`. See
|
||||||
[Duplicate keys](../../features/json_view.md#duplicate-keys).
|
[Duplicate keys](../../features/json_view.md#duplicate-keys).
|
||||||
|
|
||||||
Every other `T` -- `#!cpp std::list`, `#!cpp std::pair`, `#!cpp std::array`, user types whose `from_json()` is
|
Every other `T` -- user types whose `from_json()` is written for `BasicJsonType` only, types without a default
|
||||||
written for `BasicJsonType` only, ... -- is converted by `#!cpp materialize().get<T>()`: the subtree is built into a real `BasicJsonType`
|
constructor, `#!cpp std::tuple`s holding references, ... -- is converted by `#!cpp materialize().get<T>()`: the subtree is built into a real `BasicJsonType`
|
||||||
value first (as [`BasicJsonType::parse()`](../basic_json/parse.md) would), and converted from there exactly as
|
value first (as [`BasicJsonType::parse()`](../basic_json/parse.md) would), and converted from there exactly as
|
||||||
[`BasicJsonType::get<T>()`](../basic_json/get.md) would convert it.
|
[`BasicJsonType::get<T>()`](../basic_json/get.md) would convert it.
|
||||||
|
|
||||||
@@ -70,10 +73,10 @@ Strong guarantee: there are no changes to the view or the document it refers to.
|
|||||||
throws for the same JSON type and `T`.
|
throws for the same JSON type and `T`.
|
||||||
- For `#!cpp std::vector<U, A>`: throws `type_error.302` if the value is not an array; otherwise, whatever converting
|
- For `#!cpp std::vector<U, A>`: throws `type_error.302` if the value is not an array; otherwise, whatever converting
|
||||||
an element to `U` throws.
|
an element to `U` throws.
|
||||||
- For `#!cpp std::map`/`#!cpp std::unordered_map`: throws `type_error.302` if the value is not an object; otherwise,
|
- For `#!cpp std::map`/`#!cpp std::unordered_map` of views: throws `type_error.302` if the value is not an object.
|
||||||
whatever converting a member to the mapped type throws.
|
- For a `T` whose `from_json()` reads the view: whatever that `from_json()` throws; for the library's conversions and
|
||||||
- For a `T` whose `from_json()` reads the view: whatever that `from_json()` throws; for the macros, the same
|
the macros, the same exceptions with the same messages as [`BasicJsonType::get<T>()`](../basic_json/get.md) of the
|
||||||
exceptions with the same messages as [`BasicJsonType::get<T>()`](../basic_json/get.md) of the same value.
|
same value.
|
||||||
- For every other `T`: whatever [`materialize().get<T>()`](../basic_json/get.md) throws -- typically `type_error.302`,
|
- For every other `T`: whatever [`materialize().get<T>()`](../basic_json/get.md) throws -- typically `type_error.302`,
|
||||||
or whatever a user-provided `from_json()` throws.
|
or whatever a user-provided `from_json()` throws.
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ Converts the value to `T` and stores it in `v`, in one of three ways:
|
|||||||
|
|
||||||
- For the types that [`get<T>()`](get.md) converts directly -- arithmetic types, `#!cpp bool`,
|
- For the types that [`get<T>()`](get.md) converts directly -- arithmetic types, `#!cpp bool`,
|
||||||
`#!cpp std::nullptr_t`, [`string_view_t`](index.md#member-types), `#!cpp std::basic_string`, `BasicJsonType`,
|
`#!cpp std::nullptr_t`, [`string_view_t`](index.md#member-types), `#!cpp std::basic_string`, `BasicJsonType`,
|
||||||
`basic_json_view`, `#!cpp std::vector`, and `#!cpp std::map`/`#!cpp std::unordered_map` with string keys -- `v` is
|
`basic_json_view`, vectors of these, and maps of views -- `v` is assigned: `#!cpp v = get<T>()`.
|
||||||
assigned: `#!cpp v = get<T>()`.
|
|
||||||
- For a type whose `from_json()` accepts views (see [`get<T>()`](get.md)), that `from_json()` is called with the
|
- For a type whose `from_json()` accepts views (see [`get<T>()`](get.md)), that `from_json()` is called with the
|
||||||
view and the existing `v`, without building a `BasicJsonType` value.
|
view and the existing `v`, without building a `BasicJsonType` value.
|
||||||
- For every other type, the subtree is built into a `BasicJsonType` value and `#!cpp materialize().get_to(v)` is
|
- For every other type, the subtree is built into a `BasicJsonType` value and `#!cpp materialize().get_to(v)` is
|
||||||
|
|||||||
@@ -45,6 +45,70 @@ NLOHMANN_JSON_NAMESPACE_BEGIN
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// The from_json() overloads below read basic_json values and the views of
|
||||||
|
// <nlohmann/json_view.hpp> (BasicJsonType is then a view, and
|
||||||
|
// json_type_of_t<BasicJsonType> its basic_json type). The helpers below are
|
||||||
|
// the accesses that differ between the two.
|
||||||
|
|
||||||
|
// the enable_if parameter of the overloads that read basic_json values (written
|
||||||
|
// with negation<> because astyle spaces out a template argument list with '!')
|
||||||
|
template<typename T>
|
||||||
|
using enable_if_not_view_t = enable_if_t<negation<is_json_view<T>>::value, int>;
|
||||||
|
|
||||||
|
// the boolean of j, a boolean
|
||||||
|
template < typename BasicJsonType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
|
typename BasicJsonType::boolean_t boolean_value(const BasicJsonType& j)
|
||||||
|
{
|
||||||
|
return *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename View, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
bool boolean_value(const View& v)
|
||||||
|
{
|
||||||
|
return v.template get<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// the string of j, a string
|
||||||
|
template < typename BasicJsonType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
|
const typename BasicJsonType::string_t& string_value(const BasicJsonType& j)
|
||||||
|
{
|
||||||
|
return *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename View, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
typename View::string_t string_value(const View& v)
|
||||||
|
{
|
||||||
|
const auto s = v.get_string();
|
||||||
|
return typename View::string_t(s.data(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// the binary value of j, a binary value (never a view: a view of a JSON text
|
||||||
|
// holds no binary values)
|
||||||
|
template < typename BasicJsonType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
|
const typename BasicJsonType::binary_t& binary_value(const BasicJsonType& j)
|
||||||
|
{
|
||||||
|
return *j.template get_ptr<const typename BasicJsonType::binary_t*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename View, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
typename View::basic_json_type::binary_t binary_value(const View& /*unused*/)
|
||||||
|
{
|
||||||
|
return {}; // LCOV_EXCL_LINE
|
||||||
|
}
|
||||||
|
|
||||||
|
// the elements of j, an array, for a range-based for loop
|
||||||
|
template < typename BasicJsonType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
|
const typename BasicJsonType::array_t& array_elements(const BasicJsonType& j)
|
||||||
|
{
|
||||||
|
return *j.template get_ptr<const typename BasicJsonType::array_t*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename View, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
View array_elements(const View& v) noexcept
|
||||||
|
{
|
||||||
|
return v; // (a view is two pointers)
|
||||||
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
||||||
{
|
{
|
||||||
@@ -73,7 +137,7 @@ void from_json(const BasicJsonType& j, std::optional<T>& opt)
|
|||||||
|
|
||||||
// read a number value of any of the three number types into val;
|
// read a number value of any of the three number types into val;
|
||||||
// returns false (leaving val untouched) if j is not a number
|
// returns false (leaving val untouched) if j is not a number
|
||||||
template<typename BasicJsonType, typename ArithmeticType>
|
template < typename BasicJsonType, typename ArithmeticType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
bool get_number_value(const BasicJsonType& j, ArithmeticType& val)
|
bool get_number_value(const BasicJsonType& j, ArithmeticType& val)
|
||||||
{
|
{
|
||||||
switch (static_cast<value_t>(j))
|
switch (static_cast<value_t>(j))
|
||||||
@@ -110,10 +174,22 @@ bool get_number_value(const BasicJsonType& j, ArithmeticType& val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a view converts numbers itself (as basic_json does)
|
||||||
|
template<typename View, typename ArithmeticType, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
bool get_number_value(const View& v, ArithmeticType& val)
|
||||||
|
{
|
||||||
|
if (!v.is_number())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
val = v.template get<ArithmeticType>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// overloads for basic_json template parameters
|
// overloads for basic_json template parameters
|
||||||
template < typename BasicJsonType, typename ArithmeticType,
|
template < typename BasicJsonType, typename ArithmeticType,
|
||||||
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
!std::is_same<ArithmeticType, typename json_type_of_t<BasicJsonType>::boolean_t>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
||||||
{
|
{
|
||||||
@@ -124,31 +200,31 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
|
inline void from_json(const BasicJsonType& j, typename json_type_of_t<BasicJsonType>::boolean_t& b)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("boolean", j);
|
throw_type_must_be("boolean", j);
|
||||||
}
|
}
|
||||||
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
|
b = boolean_value(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
|
inline void from_json(const BasicJsonType& j, typename json_type_of_t<BasicJsonType>::string_t& s)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("string", j);
|
throw_type_must_be("string", j);
|
||||||
}
|
}
|
||||||
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
s = string_value(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename BasicJsonType, typename StringType,
|
typename BasicJsonType, typename StringType,
|
||||||
enable_if_t <
|
enable_if_t <
|
||||||
std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
|
std::is_assignable<StringType&, const typename json_type_of_t<BasicJsonType>::string_t>::value
|
||||||
&& is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
|
&& is_detected_exact<typename json_type_of_t<BasicJsonType>::string_t::value_type, value_type_t, StringType>::value
|
||||||
&& !std::is_same<typename BasicJsonType::string_t, StringType>::value
|
&& !std::is_same<typename json_type_of_t<BasicJsonType>::string_t, StringType>::value
|
||||||
&& !is_json_ref<StringType>::value, int > = 0 >
|
&& !is_json_ref<StringType>::value, int > = 0 >
|
||||||
inline void from_json(const BasicJsonType& j, StringType& s)
|
inline void from_json(const BasicJsonType& j, StringType& s)
|
||||||
{
|
{
|
||||||
@@ -157,23 +233,23 @@ inline void from_json(const BasicJsonType& j, StringType& s)
|
|||||||
throw_type_must_be("string", j);
|
throw_type_must_be("string", j);
|
||||||
}
|
}
|
||||||
|
|
||||||
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
s = string_value(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
|
inline void from_json(const BasicJsonType& j, typename json_type_of_t<BasicJsonType>::number_float_t& val)
|
||||||
{
|
{
|
||||||
get_arithmetic_value(j, val);
|
get_arithmetic_value(j, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, number_unsigned_overload_t<BasicJsonType>& val)
|
inline void from_json(const BasicJsonType& j, number_unsigned_overload_t<json_type_of_t<BasicJsonType>>& val)
|
||||||
{
|
{
|
||||||
get_arithmetic_value(j, val);
|
get_arithmetic_value(j, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
|
inline void from_json(const BasicJsonType& j, typename json_type_of_t<BasicJsonType>::number_integer_t& val)
|
||||||
{
|
{
|
||||||
get_arithmetic_value(j, val);
|
get_arithmetic_value(j, val);
|
||||||
}
|
}
|
||||||
@@ -185,8 +261,8 @@ inline void from_json(const BasicJsonType& j, EnumType& e)
|
|||||||
{
|
{
|
||||||
using underlying_type = typename std::underlying_type<EnumType>::type;
|
using underlying_type = typename std::underlying_type<EnumType>::type;
|
||||||
// get_arithmetic_value() does not accept boolean_t; read the number that to_json() wrote instead
|
// get_arithmetic_value() does not accept boolean_t; read the number that to_json() wrote instead
|
||||||
using value_type = typename std::conditional<std::is_same<underlying_type, typename BasicJsonType::boolean_t>::value,
|
using value_type = typename std::conditional<std::is_same<underlying_type, typename json_type_of_t<BasicJsonType>::boolean_t>::value,
|
||||||
typename BasicJsonType::number_unsigned_t, underlying_type>::type;
|
typename json_type_of_t<BasicJsonType>::number_unsigned_t, underlying_type>::type;
|
||||||
value_type val;
|
value_type val;
|
||||||
get_arithmetic_value(j, val);
|
get_arithmetic_value(j, val);
|
||||||
e = static_cast<EnumType>(bool_aware_static_cast<underlying_type>(val));
|
e = static_cast<EnumType>(bool_aware_static_cast<underlying_type>(val));
|
||||||
@@ -195,7 +271,7 @@ inline void from_json(const BasicJsonType& j, EnumType& e)
|
|||||||
|
|
||||||
// forward_list doesn't have an insert method
|
// forward_list doesn't have an insert method
|
||||||
template<typename BasicJsonType, typename T, typename Allocator,
|
template<typename BasicJsonType, typename T, typename Allocator,
|
||||||
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
|
enable_if_t<is_getable<json_type_of_t<BasicJsonType>, T>::value, int> = 0>
|
||||||
inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
|
inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
@@ -203,16 +279,16 @@ inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l
|
|||||||
throw_type_must_be("array", j);
|
throw_type_must_be("array", j);
|
||||||
}
|
}
|
||||||
l.clear();
|
l.clear();
|
||||||
std::transform(j.rbegin(), j.rend(),
|
auto pos = l.before_begin();
|
||||||
std::front_inserter(l), [](const BasicJsonType & i)
|
for (const auto& elem : array_elements(j))
|
||||||
{
|
{
|
||||||
return i.template get<T>();
|
pos = l.insert_after(pos, elem.template get<T>());
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// valarray doesn't have an insert method
|
// valarray doesn't have an insert method
|
||||||
template<typename BasicJsonType, typename T,
|
template<typename BasicJsonType, typename T,
|
||||||
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
|
enable_if_t<is_getable<json_type_of_t<BasicJsonType>, T>::value, int> = 0>
|
||||||
inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
@@ -220,11 +296,11 @@ inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
|||||||
throw_type_must_be("array", j);
|
throw_type_must_be("array", j);
|
||||||
}
|
}
|
||||||
l.resize(j.size());
|
l.resize(j.size());
|
||||||
std::transform(j.begin(), j.end(), std::begin(l),
|
std::size_t i = 0;
|
||||||
[](const BasicJsonType & elem)
|
for (const auto& elem : array_elements(j))
|
||||||
{
|
{
|
||||||
return elem.template get<T>();
|
l[i++] = elem.template get<T>();
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// element is not itself a C array: read it directly
|
// element is not itself a C array: read it directly
|
||||||
@@ -252,7 +328,8 @@ auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines
|
|||||||
from_json_c_array_element(j, arr);
|
from_json_c_array_element(j, arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
// (for a view, array_t is read element by element below)
|
||||||
|
template < typename BasicJsonType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
|
inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
|
||||||
{
|
{
|
||||||
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
|
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
|
||||||
@@ -261,7 +338,7 @@ inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType:
|
|||||||
// fill a std::array from the JSON array j: the size is checked once and the
|
// fill a std::array from the JSON array j: the size is checked once and the
|
||||||
// elements are read in order, so a short array converts the elements it has and
|
// elements are read in order, so a short array converts the elements it has and
|
||||||
// then throws the out_of_range error at() would throw for the first missing one
|
// then throws the out_of_range error at() would throw for the first missing one
|
||||||
template<typename BasicJsonType, typename T, std::size_t N>
|
template < typename BasicJsonType, typename T, std::size_t N, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
void from_json_std_array(const BasicJsonType& j, std::array<T, N>& arr)
|
void from_json_std_array(const BasicJsonType& j, std::array<T, N>& arr)
|
||||||
{
|
{
|
||||||
const auto& inner_array = *j.template get_ptr<const typename BasicJsonType::array_t*>();
|
const auto& inner_array = *j.template get_ptr<const typename BasicJsonType::array_t*>();
|
||||||
@@ -276,6 +353,21 @@ void from_json_std_array(const BasicJsonType& j, std::array<T, N>& arr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (a view has no random access to the elements: they are read in order)
|
||||||
|
template<typename View, typename T, std::size_t N, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
void from_json_std_array(const View& v, std::array<T, N>& arr)
|
||||||
|
{
|
||||||
|
std::size_t size = 0;
|
||||||
|
for (auto it = v.begin(); size < N && it != v.end(); ++it)
|
||||||
|
{
|
||||||
|
arr[size++] = (*it).template get<T>();
|
||||||
|
}
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(size < N))
|
||||||
|
{
|
||||||
|
static_cast<void>(v.at(size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T, std::size_t N>
|
template<typename BasicJsonType, typename T, std::size_t N>
|
||||||
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
|
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
|
||||||
priority_tag<2> /*unused*/)
|
priority_tag<2> /*unused*/)
|
||||||
@@ -324,9 +416,8 @@ auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, p
|
|||||||
void())
|
void())
|
||||||
{
|
{
|
||||||
ConstructibleArrayType ret;
|
ConstructibleArrayType ret;
|
||||||
const auto* inner_array = j.template get_ptr<const typename BasicJsonType::array_t*>();
|
reserve_if_possible(ret, j.size(), priority_tag<1> {});
|
||||||
reserve_if_possible(ret, inner_array->size(), priority_tag<1> {});
|
for (const auto& elem : array_elements(j))
|
||||||
for (const auto& elem : *inner_array)
|
|
||||||
{
|
{
|
||||||
// get<BasicJsonType>() returns *this, this won't call a from_json
|
// get<BasicJsonType>() returns *this, this won't call a from_json
|
||||||
// method when value_type is BasicJsonType
|
// method when value_type is BasicJsonType
|
||||||
@@ -337,11 +428,11 @@ auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, p
|
|||||||
|
|
||||||
template < typename BasicJsonType, typename ConstructibleArrayType,
|
template < typename BasicJsonType, typename ConstructibleArrayType,
|
||||||
enable_if_t <
|
enable_if_t <
|
||||||
is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
|
is_constructible_array_type<json_type_of_t<BasicJsonType>, ConstructibleArrayType>::value&&
|
||||||
!is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
|
!is_constructible_object_type<json_type_of_t<BasicJsonType>, ConstructibleArrayType>::value&&
|
||||||
!is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
|
!is_constructible_string_type<json_type_of_t<BasicJsonType>, ConstructibleArrayType>::value&&
|
||||||
!std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
|
!std::is_same<ConstructibleArrayType, typename json_type_of_t<BasicJsonType>::binary_t>::value&&
|
||||||
!is_compatible_binary_type<BasicJsonType, ConstructibleArrayType>::value&&
|
!is_compatible_binary_type<json_type_of_t<BasicJsonType>, ConstructibleArrayType>::value&&
|
||||||
!is_basic_json<ConstructibleArrayType>::value,
|
!is_basic_json<ConstructibleArrayType>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
|
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
|
||||||
@@ -408,24 +499,24 @@ auto from_json(const BasicJsonType& j, identity_tag<std::array<T, N>> tag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
|
inline void from_json(const BasicJsonType& j, typename json_type_of_t<BasicJsonType>::binary_t& bin)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("binary", j);
|
throw_type_must_be("binary", j);
|
||||||
}
|
}
|
||||||
|
|
||||||
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
|
bin = binary_value(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename CompatibleArrayType,
|
template < typename BasicJsonType, typename CompatibleArrayType,
|
||||||
enable_if_t < is_compatible_binary_type<BasicJsonType, CompatibleArrayType>::value,
|
enable_if_t < is_compatible_binary_type<json_type_of_t<BasicJsonType>, CompatibleArrayType>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
inline void from_json(const BasicJsonType& j, CompatibleArrayType& bin)
|
inline void from_json(const BasicJsonType& j, CompatibleArrayType& bin)
|
||||||
{
|
{
|
||||||
if (j.is_binary())
|
if (j.is_binary())
|
||||||
{
|
{
|
||||||
bin = static_cast<CompatibleArrayType>(*j.template get_ptr<const typename BasicJsonType::binary_t*>());
|
bin = static_cast<CompatibleArrayType>(binary_value(j));
|
||||||
}
|
}
|
||||||
else if (j.is_array())
|
else if (j.is_array())
|
||||||
{
|
{
|
||||||
@@ -454,8 +545,47 @@ void from_json_object_emplace(ConstructibleObjectType& obj, Key&& key, Value&& v
|
|||||||
obj.emplace(std::forward<Key>(key), std::forward<Value>(value));
|
obj.emplace(std::forward<Key>(key), std::forward<Value>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a member of a view's object: a later member with the same key replaces an
|
||||||
|
// earlier one, as parse() keeps the last value of a repeated key (containers
|
||||||
|
// without operator[] keep the first)
|
||||||
|
template<typename ConstructibleObjectType, typename Key, typename Value>
|
||||||
|
auto from_json_object_assign(ConstructibleObjectType& obj, Key&& key, Value&& value, priority_tag<1> /*unused*/)
|
||||||
|
-> decltype(obj[std::forward<Key>(key)] = std::forward<Value>(value), void())
|
||||||
|
{
|
||||||
|
obj[std::forward<Key>(key)] = std::forward<Value>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ConstructibleObjectType, typename Key, typename Value>
|
||||||
|
void from_json_object_assign(ConstructibleObjectType& obj, Key&& key, Value&& value, priority_tag<0> /*unused*/)
|
||||||
|
{
|
||||||
|
obj.emplace(std::forward<Key>(key), std::forward<Value>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename BasicJsonType, typename ConstructibleObjectType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
|
void from_json_object_impl(const BasicJsonType& j, ConstructibleObjectType& ret)
|
||||||
|
{
|
||||||
|
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
|
||||||
|
reserve_if_possible(ret, inner_object->size(), priority_tag<1> {});
|
||||||
|
for (const auto& p : *inner_object)
|
||||||
|
{
|
||||||
|
from_json_object_emplace(ret, p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>(), priority_tag<1> {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename View, typename ConstructibleObjectType, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
void from_json_object_impl(const View& v, ConstructibleObjectType& ret)
|
||||||
|
{
|
||||||
|
using string_t = typename View::basic_json_type::object_t::key_type;
|
||||||
|
reserve_if_possible(ret, v.size(), priority_tag<1> {});
|
||||||
|
for (const auto item : v.items())
|
||||||
|
{
|
||||||
|
const auto key = item.key();
|
||||||
|
from_json_object_assign(ret, string_t(key.data(), key.size()), item.value().template get<typename ConstructibleObjectType::mapped_type>(), priority_tag<1> {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename ConstructibleObjectType,
|
template<typename BasicJsonType, typename ConstructibleObjectType,
|
||||||
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
|
enable_if_t<is_constructible_object_type<json_type_of_t<BasicJsonType>, ConstructibleObjectType>::value, int> = 0>
|
||||||
inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
|
||||||
@@ -464,12 +594,7 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ConstructibleObjectType ret;
|
ConstructibleObjectType ret;
|
||||||
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
|
from_json_object_impl(j, ret);
|
||||||
reserve_if_possible(ret, inner_object->size(), priority_tag<1> {});
|
|
||||||
for (const auto& p : *inner_object)
|
|
||||||
{
|
|
||||||
from_json_object_emplace(ret, p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>(), priority_tag<1> {});
|
|
||||||
}
|
|
||||||
obj = std::move(ret);
|
obj = std::move(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,10 +603,10 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
|||||||
template < typename BasicJsonType, typename ArithmeticType,
|
template < typename BasicJsonType, typename ArithmeticType,
|
||||||
enable_if_t <
|
enable_if_t <
|
||||||
std::is_arithmetic<ArithmeticType>::value&&
|
std::is_arithmetic<ArithmeticType>::value&&
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
|
!std::is_same<ArithmeticType, typename json_type_of_t<BasicJsonType>::number_unsigned_t>::value&&
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
|
!std::is_same<ArithmeticType, typename json_type_of_t<BasicJsonType>::number_integer_t>::value&&
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
|
!std::is_same<ArithmeticType, typename json_type_of_t<BasicJsonType>::number_float_t>::value&&
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
!std::is_same<ArithmeticType, typename json_type_of_t<BasicJsonType>::boolean_t>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
inline void from_json(const BasicJsonType& j, ArithmeticType& val)
|
inline void from_json(const BasicJsonType& j, ArithmeticType& val)
|
||||||
{
|
{
|
||||||
@@ -495,7 +620,7 @@ inline void from_json(const BasicJsonType& j, ArithmeticType& val)
|
|||||||
{
|
{
|
||||||
throw_type_must_be("number", j);
|
throw_type_must_be("number", j);
|
||||||
}
|
}
|
||||||
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
|
val = static_cast<ArithmeticType>(boolean_value(j));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename Type>
|
template<typename BasicJsonType, typename Type>
|
||||||
@@ -505,7 +630,7 @@ detail::uncvref_t<Type> from_json_tuple_get_impl(BasicJsonType&& j, detail::iden
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename Type,
|
template<typename BasicJsonType, typename Type,
|
||||||
detail::enable_if_t<detail::is_compatible_reference_type<BasicJsonType, Type>::value, int> = 0>
|
detail::enable_if_t<conjunction<is_basic_json<uncvref_t<BasicJsonType>>, is_compatible_reference_type<BasicJsonType, Type>>::value, int> = 0>
|
||||||
Type from_json_tuple_get_impl(BasicJsonType && j, detail::identity_tag<Type> /*unused*/, detail::priority_tag<1> /*unused*/)
|
Type from_json_tuple_get_impl(BasicJsonType && j, detail::identity_tag<Type> /*unused*/, detail::priority_tag<1> /*unused*/)
|
||||||
{
|
{
|
||||||
return std::forward<BasicJsonType>(j).template get_ref<Type>();
|
return std::forward<BasicJsonType>(j).template get_ref<Type>();
|
||||||
@@ -549,7 +674,7 @@ inline void from_json_tuple_impl(const BasicJsonType& j, std::pair<A1, A2>& p, p
|
|||||||
template<typename BasicJsonType, typename... Args>
|
template<typename BasicJsonType, typename... Args>
|
||||||
std::tuple<Args...> from_json_tuple_impl(const BasicJsonType& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
|
std::tuple<Args...> from_json_tuple_impl(const BasicJsonType& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
|
||||||
{
|
{
|
||||||
static_assert(conjunction<disjunction<negation<std::is_reference<Args>>, is_compatible_reference_type<const BasicJsonType&, Args>>...>::value,
|
static_assert(conjunction<disjunction<negation<std::is_reference<Args>>, conjunction<is_basic_json<BasicJsonType>, is_compatible_reference_type<const BasicJsonType&, Args>>>...>::value,
|
||||||
"Can not return a tuple containing references to types not contained in a Json, try Json::get_to()");
|
"Can not return a tuple containing references to types not contained in a Json, try Json::get_to()");
|
||||||
return from_json_tuple_impl_base<1, Args...>(j, index_sequence_for<Args...> {});
|
return from_json_tuple_impl_base<1, Args...>(j, index_sequence_for<Args...> {});
|
||||||
}
|
}
|
||||||
@@ -595,7 +720,7 @@ void from_json_pair_array_to_map(const BasicJsonType& j, MapType& m)
|
|||||||
// read a map with enum keys from an object, using the enum's own from_json for
|
// read a map with enum keys from an object, using the enum's own from_json for
|
||||||
// the keys (e.g., from NLOHMANN_JSON_SERIALIZE_ENUM); this is the form written
|
// the keys (e.g., from NLOHMANN_JSON_SERIALIZE_ENUM); this is the form written
|
||||||
// with JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
// with JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||||
template<typename BasicJsonType, typename Map>
|
template < typename BasicJsonType, typename Map, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
inline bool from_json_enum_keyed_object(const BasicJsonType& j, Map& m, std::true_type /*key is enum*/)
|
inline bool from_json_enum_keyed_object(const BasicJsonType& j, Map& m, std::true_type /*key is enum*/)
|
||||||
{
|
{
|
||||||
if (!j.is_object())
|
if (!j.is_object())
|
||||||
@@ -610,6 +735,24 @@ inline bool from_json_enum_keyed_object(const BasicJsonType& j, Map& m, std::tru
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename View, typename Map, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
inline bool from_json_enum_keyed_object(const View& v, Map& m, std::true_type /*key is enum*/)
|
||||||
|
{
|
||||||
|
using json_t = typename View::basic_json_type;
|
||||||
|
if (!v.is_object())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m.clear();
|
||||||
|
for (const auto item : v.items())
|
||||||
|
{
|
||||||
|
const auto key = item.key();
|
||||||
|
from_json_object_assign(m, json_t(typename json_t::string_t(key.data(), key.size())).template get<typename Map::key_type>(),
|
||||||
|
item.value().template get<typename Map::mapped_type>(), priority_tag<1> {});
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename Map>
|
template<typename BasicJsonType, typename Map>
|
||||||
inline bool from_json_enum_keyed_object(const BasicJsonType& /*j*/, Map& /*m*/, std::false_type /*key is enum*/)
|
inline bool from_json_enum_keyed_object(const BasicJsonType& /*j*/, Map& /*m*/, std::false_type /*key is enum*/)
|
||||||
{
|
{
|
||||||
@@ -618,7 +761,7 @@ inline bool from_json_enum_keyed_object(const BasicJsonType& /*j*/, Map& /*m*/,
|
|||||||
|
|
||||||
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
|
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
|
||||||
typename = enable_if_t < !std::is_constructible <
|
typename = enable_if_t < !std::is_constructible <
|
||||||
typename BasicJsonType::string_t, Key >::value >>
|
typename json_type_of_t<BasicJsonType>::string_t, Key >::value >>
|
||||||
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
|
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(modernize-type-traits) we use C++11
|
// NOLINTNEXTLINE(modernize-type-traits) we use C++11
|
||||||
@@ -631,7 +774,7 @@ void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>&
|
|||||||
|
|
||||||
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
|
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
|
||||||
typename = enable_if_t < !std::is_constructible <
|
typename = enable_if_t < !std::is_constructible <
|
||||||
typename BasicJsonType::string_t, Key >::value >>
|
typename json_type_of_t<BasicJsonType>::string_t, Key >::value >>
|
||||||
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
|
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(modernize-type-traits) we use C++11
|
// NOLINTNEXTLINE(modernize-type-traits) we use C++11
|
||||||
@@ -655,7 +798,7 @@ inline void from_json(const BasicJsonType& j, std_fs::path& p)
|
|||||||
{
|
{
|
||||||
throw_type_must_be("string", j);
|
throw_type_must_be("string", j);
|
||||||
}
|
}
|
||||||
const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
const auto& s = string_value(j);
|
||||||
// Checking for C++20 standard or later can be insufficient in case the
|
// Checking for C++20 standard or later can be insufficient in case the
|
||||||
// library support for char8_t is either incomplete or was disabled
|
// library support for char8_t is either incomplete or was disabled
|
||||||
// altogether. Use the __cpp_lib_char8_t feature test instead.
|
// altogether. Use the __cpp_lib_char8_t feature test instead.
|
||||||
@@ -694,10 +837,9 @@ struct fn
|
|||||||
};
|
};
|
||||||
} // namespace from_json_adl
|
} // namespace from_json_adl
|
||||||
|
|
||||||
// the sources whose from_json() is only looked up by ADL: views (the library's
|
// the sources whose from_json() is only looked up by ADL: the probe
|
||||||
// overloads are written for basic_json) and the probe
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct is_adl_only_from_json_source : disjunction<is_json_view<T>, std::is_same<T, from_json_adl::probe>> {};
|
struct is_adl_only_from_json_source : std::is_same<T, from_json_adl::probe> {};
|
||||||
|
|
||||||
struct from_json_fn
|
struct from_json_fn
|
||||||
{
|
{
|
||||||
@@ -748,20 +890,6 @@ void from_json_base(const View& v, T& base)
|
|||||||
v.get_to(base);
|
v.get_to(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the context of an exception thrown by a from_json() of the macros: the value
|
|
||||||
// itself for basic_json (for JSON_DIAGNOSTICS), none for a view
|
|
||||||
template<typename BasicJsonType, enable_if_t<is_basic_json<BasicJsonType>::value, int> = 0>
|
|
||||||
const BasicJsonType * from_json_context(const BasicJsonType& j) noexcept
|
|
||||||
{
|
|
||||||
return &j;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename View, enable_if_t<is_json_view<View>::value, int> = 0>
|
|
||||||
std::nullptr_t from_json_context(const View& /*unused*/) noexcept
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// a value as an exception message shows it (invalid UTF-8 replaced; the
|
// a value as an exception message shows it (invalid UTF-8 replaced; the
|
||||||
// strings of a view are always valid UTF-8)
|
// strings of a view are always valid UTF-8)
|
||||||
template<typename BasicJsonType, enable_if_t<is_basic_json<BasicJsonType>::value, int> = 0>
|
template<typename BasicJsonType, enable_if_t<is_basic_json<BasicJsonType>::value, int> = 0>
|
||||||
|
|||||||
@@ -417,6 +417,20 @@ void templated_json_throw(ExceptionType exception)
|
|||||||
(void)exception;
|
(void)exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the context of an exception about j: j itself for a basic_json value (whose
|
||||||
|
// path JSON_DIAGNOSTICS shows), none for a view of <nlohmann/json_view.hpp>
|
||||||
|
template<typename BasicJsonType, enable_if_t<is_basic_json<BasicJsonType>::value, int> = 0>
|
||||||
|
const BasicJsonType * exception_context(const BasicJsonType& j) noexcept
|
||||||
|
{
|
||||||
|
return &j;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename View, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
std::nullptr_t exception_context(const View& /*unused*/) noexcept
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief throws because @a j does not have the type a conversion expects
|
@brief throws because @a j does not have the type a conversion expects
|
||||||
@param[in] expected the expected type(s), e.g. "array" or "binary or array"
|
@param[in] expected the expected type(s), e.g. "array" or "binary or array"
|
||||||
@@ -428,7 +442,7 @@ JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_type_must_be(const cha
|
|||||||
{
|
{
|
||||||
static_cast<void>(expected); // unused when JSON_NOEXCEPTION is defined
|
static_cast<void>(expected); // unused when JSON_NOEXCEPTION is defined
|
||||||
static_cast<void>(j);
|
static_cast<void>(j);
|
||||||
JSON_THROW(type_error::create(exception_id::type_mismatch, concat("type must be ", expected, ", but is ", j.type_name()), &j));
|
JSON_THROW(type_error::create(exception_id::type_mismatch, concat("type must be ", expected, ", but is ", j.type_name()), exception_context(j)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
@@ -347,7 +347,7 @@
|
|||||||
return ej_pair.second == j; \
|
return ej_pair.second == j; \
|
||||||
}); \
|
}); \
|
||||||
if (it != std::end(m)) e = it->first; \
|
if (it != std::end(m)) e = it->first; \
|
||||||
else ::nlohmann::detail::templated_json_throw<nlohmann::detail::out_of_range>(nlohmann::detail::out_of_range::create(nlohmann::detail::exception_id::value_out_of_range, nlohmann::detail::concat("enum value out of range for " #ENUM_TYPE ": ", nlohmann::detail::from_json_dump(j)), nlohmann::detail::from_json_context(j))); \
|
else ::nlohmann::detail::templated_json_throw<nlohmann::detail::out_of_range>(nlohmann::detail::out_of_range::create(nlohmann::detail::exception_id::value_out_of_range, nlohmann::detail::concat("enum value out of range for " #ENUM_TYPE ": ", nlohmann::detail::from_json_dump(j)), nlohmann::detail::exception_context(j))); \
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
|
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
|
||||||
|
|||||||
@@ -130,14 +130,16 @@ struct is_direct_value : std::integral_constant < bool,
|
|||||||
template<typename Traits, typename Alloc, typename BasicJsonType, typename View>
|
template<typename Traits, typename Alloc, typename BasicJsonType, typename View>
|
||||||
struct is_direct_value<std::basic_string<char, Traits, Alloc>, BasicJsonType, View> : std::true_type {};
|
struct is_direct_value<std::basic_string<char, Traits, Alloc>, BasicJsonType, View> : std::true_type {};
|
||||||
|
|
||||||
|
// (vectors of these, which are faster than through from_json(), and containers
|
||||||
|
// of views; other containers are read by the library's from_json())
|
||||||
template<typename U, typename A, typename BasicJsonType, typename View>
|
template<typename U, typename A, typename BasicJsonType, typename View>
|
||||||
struct is_direct_value<std::vector<U, A>, BasicJsonType, View> : std::true_type {};
|
struct is_direct_value<std::vector<U, A>, BasicJsonType, View> : is_direct_value<U, BasicJsonType, View> {};
|
||||||
|
|
||||||
template<typename K, typename V, typename C, typename A, typename BasicJsonType, typename View>
|
template<typename K, typename C, typename A, typename BasicJsonType, typename View>
|
||||||
struct is_direct_value<std::map<K, V, C, A>, BasicJsonType, View> : is_string_key<K> {};
|
struct is_direct_value<std::map<K, View, C, A>, BasicJsonType, View> : is_string_key<K> {};
|
||||||
|
|
||||||
template<typename K, typename V, typename H, typename E, typename A, typename BasicJsonType, typename View>
|
template<typename K, typename H, typename E, typename A, typename BasicJsonType, typename View>
|
||||||
struct is_direct_value<std::unordered_map<K, V, H, E, A>, BasicJsonType, View> : is_string_key<K> {};
|
struct is_direct_value<std::unordered_map<K, View, H, E, A>, BasicJsonType, View> : is_string_key<K> {};
|
||||||
|
|
||||||
} // namespace view
|
} // namespace view
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@@ -910,22 +910,25 @@ class basic_json_view
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename A>
|
/// vectors of the types converted directly (faster than the library's
|
||||||
|
/// from_json()) and containers of views (no from_json() reads them: a view
|
||||||
|
/// is no value of BasicJsonType); other containers are read by from_json()
|
||||||
|
template < typename U, typename A, typename std::enable_if < detail::view::is_direct_value<U, BasicJsonType, basic_json_view>::value, int >::type = 0 >
|
||||||
std::vector<U, A> get_impl(detail::view::value_tag<std::vector<U, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
|
std::vector<U, A> get_impl(detail::view::value_tag<std::vector<U, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
|
||||||
{
|
{
|
||||||
return detail::view::vector_value<basic_json_view, U, A>(*this);
|
return detail::view::vector_value<basic_json_view, U, A>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename K, typename V, typename C, typename A, typename std::enable_if<detail::view::is_string_key<K>::value, int>::type = 0>
|
template<typename K, typename C, typename A, typename std::enable_if<detail::view::is_string_key<K>::value, int>::type = 0>
|
||||||
std::map<K, V, C, A> get_impl(detail::view::value_tag<std::map<K, V, C, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
|
std::map<K, basic_json_view, C, A> get_impl(detail::view::value_tag<std::map<K, basic_json_view, C, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
|
||||||
{
|
{
|
||||||
return detail::view::map_value<std::map<K, V, C, A>>(*this);
|
return detail::view::map_value<std::map<K, basic_json_view, C, A>>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename K, typename V, typename H, typename E, typename A, typename std::enable_if<detail::view::is_string_key<K>::value, int>::type = 0>
|
template<typename K, typename H, typename E, typename A, typename std::enable_if<detail::view::is_string_key<K>::value, int>::type = 0>
|
||||||
std::unordered_map<K, V, H, E, A> get_impl(detail::view::value_tag<std::unordered_map<K, V, H, E, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
|
std::unordered_map<K, basic_json_view, H, E, A> get_impl(detail::view::value_tag<std::unordered_map<K, basic_json_view, H, E, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
|
||||||
{
|
{
|
||||||
return detail::view::map_value<std::unordered_map<K, V, H, E, A>>(*this);
|
return detail::view::map_value<std::unordered_map<K, basic_json_view, H, E, A>>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// whether the from_json() of T's serializer reads views (see
|
/// whether the from_json() of T's serializer reads views (see
|
||||||
|
|||||||
Generated
+218
-76
@@ -2720,7 +2720,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP
|
|||||||
return ej_pair.second == j; \
|
return ej_pair.second == j; \
|
||||||
}); \
|
}); \
|
||||||
if (it != std::end(m)) e = it->first; \
|
if (it != std::end(m)) e = it->first; \
|
||||||
else ::nlohmann::detail::templated_json_throw<nlohmann::detail::out_of_range>(nlohmann::detail::out_of_range::create(nlohmann::detail::exception_id::value_out_of_range, nlohmann::detail::concat("enum value out of range for " #ENUM_TYPE ": ", nlohmann::detail::from_json_dump(j)), nlohmann::detail::from_json_context(j))); \
|
else ::nlohmann::detail::templated_json_throw<nlohmann::detail::out_of_range>(nlohmann::detail::out_of_range::create(nlohmann::detail::exception_id::value_out_of_range, nlohmann::detail::concat("enum value out of range for " #ENUM_TYPE ": ", nlohmann::detail::from_json_dump(j)), nlohmann::detail::exception_context(j))); \
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
|
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
|
||||||
@@ -5914,6 +5914,20 @@ void templated_json_throw(ExceptionType exception)
|
|||||||
(void)exception;
|
(void)exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the context of an exception about j: j itself for a basic_json value (whose
|
||||||
|
// path JSON_DIAGNOSTICS shows), none for a view of <nlohmann/json_view.hpp>
|
||||||
|
template<typename BasicJsonType, enable_if_t<is_basic_json<BasicJsonType>::value, int> = 0>
|
||||||
|
const BasicJsonType * exception_context(const BasicJsonType& j) noexcept
|
||||||
|
{
|
||||||
|
return &j;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename View, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
std::nullptr_t exception_context(const View& /*unused*/) noexcept
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief throws because @a j does not have the type a conversion expects
|
@brief throws because @a j does not have the type a conversion expects
|
||||||
@param[in] expected the expected type(s), e.g. "array" or "binary or array"
|
@param[in] expected the expected type(s), e.g. "array" or "binary or array"
|
||||||
@@ -5925,7 +5939,7 @@ JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_type_must_be(const cha
|
|||||||
{
|
{
|
||||||
static_cast<void>(expected); // unused when JSON_NOEXCEPTION is defined
|
static_cast<void>(expected); // unused when JSON_NOEXCEPTION is defined
|
||||||
static_cast<void>(j);
|
static_cast<void>(j);
|
||||||
JSON_THROW(type_error::create(exception_id::type_mismatch, concat("type must be ", expected, ", but is ", j.type_name()), &j));
|
JSON_THROW(type_error::create(exception_id::type_mismatch, concat("type must be ", expected, ", but is ", j.type_name()), exception_context(j)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -6154,6 +6168,70 @@ NLOHMANN_JSON_NAMESPACE_BEGIN
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// The from_json() overloads below read basic_json values and the views of
|
||||||
|
// <nlohmann/json_view.hpp> (BasicJsonType is then a view, and
|
||||||
|
// json_type_of_t<BasicJsonType> its basic_json type). The helpers below are
|
||||||
|
// the accesses that differ between the two.
|
||||||
|
|
||||||
|
// the enable_if parameter of the overloads that read basic_json values (written
|
||||||
|
// with negation<> because astyle spaces out a template argument list with '!')
|
||||||
|
template<typename T>
|
||||||
|
using enable_if_not_view_t = enable_if_t<negation<is_json_view<T>>::value, int>;
|
||||||
|
|
||||||
|
// the boolean of j, a boolean
|
||||||
|
template < typename BasicJsonType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
|
typename BasicJsonType::boolean_t boolean_value(const BasicJsonType& j)
|
||||||
|
{
|
||||||
|
return *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename View, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
bool boolean_value(const View& v)
|
||||||
|
{
|
||||||
|
return v.template get<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// the string of j, a string
|
||||||
|
template < typename BasicJsonType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
|
const typename BasicJsonType::string_t& string_value(const BasicJsonType& j)
|
||||||
|
{
|
||||||
|
return *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename View, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
typename View::string_t string_value(const View& v)
|
||||||
|
{
|
||||||
|
const auto s = v.get_string();
|
||||||
|
return typename View::string_t(s.data(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// the binary value of j, a binary value (never a view: a view of a JSON text
|
||||||
|
// holds no binary values)
|
||||||
|
template < typename BasicJsonType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
|
const typename BasicJsonType::binary_t& binary_value(const BasicJsonType& j)
|
||||||
|
{
|
||||||
|
return *j.template get_ptr<const typename BasicJsonType::binary_t*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename View, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
typename View::basic_json_type::binary_t binary_value(const View& /*unused*/)
|
||||||
|
{
|
||||||
|
return {}; // LCOV_EXCL_LINE
|
||||||
|
}
|
||||||
|
|
||||||
|
// the elements of j, an array, for a range-based for loop
|
||||||
|
template < typename BasicJsonType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
|
const typename BasicJsonType::array_t& array_elements(const BasicJsonType& j)
|
||||||
|
{
|
||||||
|
return *j.template get_ptr<const typename BasicJsonType::array_t*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename View, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
View array_elements(const View& v) noexcept
|
||||||
|
{
|
||||||
|
return v; // (a view is two pointers)
|
||||||
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
||||||
{
|
{
|
||||||
@@ -6182,7 +6260,7 @@ void from_json(const BasicJsonType& j, std::optional<T>& opt)
|
|||||||
|
|
||||||
// read a number value of any of the three number types into val;
|
// read a number value of any of the three number types into val;
|
||||||
// returns false (leaving val untouched) if j is not a number
|
// returns false (leaving val untouched) if j is not a number
|
||||||
template<typename BasicJsonType, typename ArithmeticType>
|
template < typename BasicJsonType, typename ArithmeticType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
bool get_number_value(const BasicJsonType& j, ArithmeticType& val)
|
bool get_number_value(const BasicJsonType& j, ArithmeticType& val)
|
||||||
{
|
{
|
||||||
switch (static_cast<value_t>(j))
|
switch (static_cast<value_t>(j))
|
||||||
@@ -6219,10 +6297,22 @@ bool get_number_value(const BasicJsonType& j, ArithmeticType& val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a view converts numbers itself (as basic_json does)
|
||||||
|
template<typename View, typename ArithmeticType, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
bool get_number_value(const View& v, ArithmeticType& val)
|
||||||
|
{
|
||||||
|
if (!v.is_number())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
val = v.template get<ArithmeticType>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// overloads for basic_json template parameters
|
// overloads for basic_json template parameters
|
||||||
template < typename BasicJsonType, typename ArithmeticType,
|
template < typename BasicJsonType, typename ArithmeticType,
|
||||||
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
!std::is_same<ArithmeticType, typename json_type_of_t<BasicJsonType>::boolean_t>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
||||||
{
|
{
|
||||||
@@ -6233,31 +6323,31 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
|
inline void from_json(const BasicJsonType& j, typename json_type_of_t<BasicJsonType>::boolean_t& b)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("boolean", j);
|
throw_type_must_be("boolean", j);
|
||||||
}
|
}
|
||||||
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
|
b = boolean_value(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
|
inline void from_json(const BasicJsonType& j, typename json_type_of_t<BasicJsonType>::string_t& s)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("string", j);
|
throw_type_must_be("string", j);
|
||||||
}
|
}
|
||||||
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
s = string_value(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename BasicJsonType, typename StringType,
|
typename BasicJsonType, typename StringType,
|
||||||
enable_if_t <
|
enable_if_t <
|
||||||
std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
|
std::is_assignable<StringType&, const typename json_type_of_t<BasicJsonType>::string_t>::value
|
||||||
&& is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
|
&& is_detected_exact<typename json_type_of_t<BasicJsonType>::string_t::value_type, value_type_t, StringType>::value
|
||||||
&& !std::is_same<typename BasicJsonType::string_t, StringType>::value
|
&& !std::is_same<typename json_type_of_t<BasicJsonType>::string_t, StringType>::value
|
||||||
&& !is_json_ref<StringType>::value, int > = 0 >
|
&& !is_json_ref<StringType>::value, int > = 0 >
|
||||||
inline void from_json(const BasicJsonType& j, StringType& s)
|
inline void from_json(const BasicJsonType& j, StringType& s)
|
||||||
{
|
{
|
||||||
@@ -6266,23 +6356,23 @@ inline void from_json(const BasicJsonType& j, StringType& s)
|
|||||||
throw_type_must_be("string", j);
|
throw_type_must_be("string", j);
|
||||||
}
|
}
|
||||||
|
|
||||||
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
s = string_value(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
|
inline void from_json(const BasicJsonType& j, typename json_type_of_t<BasicJsonType>::number_float_t& val)
|
||||||
{
|
{
|
||||||
get_arithmetic_value(j, val);
|
get_arithmetic_value(j, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, number_unsigned_overload_t<BasicJsonType>& val)
|
inline void from_json(const BasicJsonType& j, number_unsigned_overload_t<json_type_of_t<BasicJsonType>>& val)
|
||||||
{
|
{
|
||||||
get_arithmetic_value(j, val);
|
get_arithmetic_value(j, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
|
inline void from_json(const BasicJsonType& j, typename json_type_of_t<BasicJsonType>::number_integer_t& val)
|
||||||
{
|
{
|
||||||
get_arithmetic_value(j, val);
|
get_arithmetic_value(j, val);
|
||||||
}
|
}
|
||||||
@@ -6294,8 +6384,8 @@ inline void from_json(const BasicJsonType& j, EnumType& e)
|
|||||||
{
|
{
|
||||||
using underlying_type = typename std::underlying_type<EnumType>::type;
|
using underlying_type = typename std::underlying_type<EnumType>::type;
|
||||||
// get_arithmetic_value() does not accept boolean_t; read the number that to_json() wrote instead
|
// get_arithmetic_value() does not accept boolean_t; read the number that to_json() wrote instead
|
||||||
using value_type = typename std::conditional<std::is_same<underlying_type, typename BasicJsonType::boolean_t>::value,
|
using value_type = typename std::conditional<std::is_same<underlying_type, typename json_type_of_t<BasicJsonType>::boolean_t>::value,
|
||||||
typename BasicJsonType::number_unsigned_t, underlying_type>::type;
|
typename json_type_of_t<BasicJsonType>::number_unsigned_t, underlying_type>::type;
|
||||||
value_type val;
|
value_type val;
|
||||||
get_arithmetic_value(j, val);
|
get_arithmetic_value(j, val);
|
||||||
e = static_cast<EnumType>(bool_aware_static_cast<underlying_type>(val));
|
e = static_cast<EnumType>(bool_aware_static_cast<underlying_type>(val));
|
||||||
@@ -6304,7 +6394,7 @@ inline void from_json(const BasicJsonType& j, EnumType& e)
|
|||||||
|
|
||||||
// forward_list doesn't have an insert method
|
// forward_list doesn't have an insert method
|
||||||
template<typename BasicJsonType, typename T, typename Allocator,
|
template<typename BasicJsonType, typename T, typename Allocator,
|
||||||
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
|
enable_if_t<is_getable<json_type_of_t<BasicJsonType>, T>::value, int> = 0>
|
||||||
inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
|
inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
@@ -6312,16 +6402,16 @@ inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l
|
|||||||
throw_type_must_be("array", j);
|
throw_type_must_be("array", j);
|
||||||
}
|
}
|
||||||
l.clear();
|
l.clear();
|
||||||
std::transform(j.rbegin(), j.rend(),
|
auto pos = l.before_begin();
|
||||||
std::front_inserter(l), [](const BasicJsonType & i)
|
for (const auto& elem : array_elements(j))
|
||||||
{
|
{
|
||||||
return i.template get<T>();
|
pos = l.insert_after(pos, elem.template get<T>());
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// valarray doesn't have an insert method
|
// valarray doesn't have an insert method
|
||||||
template<typename BasicJsonType, typename T,
|
template<typename BasicJsonType, typename T,
|
||||||
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
|
enable_if_t<is_getable<json_type_of_t<BasicJsonType>, T>::value, int> = 0>
|
||||||
inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
@@ -6329,11 +6419,11 @@ inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
|||||||
throw_type_must_be("array", j);
|
throw_type_must_be("array", j);
|
||||||
}
|
}
|
||||||
l.resize(j.size());
|
l.resize(j.size());
|
||||||
std::transform(j.begin(), j.end(), std::begin(l),
|
std::size_t i = 0;
|
||||||
[](const BasicJsonType & elem)
|
for (const auto& elem : array_elements(j))
|
||||||
{
|
{
|
||||||
return elem.template get<T>();
|
l[i++] = elem.template get<T>();
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// element is not itself a C array: read it directly
|
// element is not itself a C array: read it directly
|
||||||
@@ -6361,7 +6451,8 @@ auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines
|
|||||||
from_json_c_array_element(j, arr);
|
from_json_c_array_element(j, arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
// (for a view, array_t is read element by element below)
|
||||||
|
template < typename BasicJsonType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
|
inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
|
||||||
{
|
{
|
||||||
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
|
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
|
||||||
@@ -6370,7 +6461,7 @@ inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType:
|
|||||||
// fill a std::array from the JSON array j: the size is checked once and the
|
// fill a std::array from the JSON array j: the size is checked once and the
|
||||||
// elements are read in order, so a short array converts the elements it has and
|
// elements are read in order, so a short array converts the elements it has and
|
||||||
// then throws the out_of_range error at() would throw for the first missing one
|
// then throws the out_of_range error at() would throw for the first missing one
|
||||||
template<typename BasicJsonType, typename T, std::size_t N>
|
template < typename BasicJsonType, typename T, std::size_t N, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
void from_json_std_array(const BasicJsonType& j, std::array<T, N>& arr)
|
void from_json_std_array(const BasicJsonType& j, std::array<T, N>& arr)
|
||||||
{
|
{
|
||||||
const auto& inner_array = *j.template get_ptr<const typename BasicJsonType::array_t*>();
|
const auto& inner_array = *j.template get_ptr<const typename BasicJsonType::array_t*>();
|
||||||
@@ -6385,6 +6476,21 @@ void from_json_std_array(const BasicJsonType& j, std::array<T, N>& arr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (a view has no random access to the elements: they are read in order)
|
||||||
|
template<typename View, typename T, std::size_t N, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
void from_json_std_array(const View& v, std::array<T, N>& arr)
|
||||||
|
{
|
||||||
|
std::size_t size = 0;
|
||||||
|
for (auto it = v.begin(); size < N && it != v.end(); ++it)
|
||||||
|
{
|
||||||
|
arr[size++] = (*it).template get<T>();
|
||||||
|
}
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(size < N))
|
||||||
|
{
|
||||||
|
static_cast<void>(v.at(size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T, std::size_t N>
|
template<typename BasicJsonType, typename T, std::size_t N>
|
||||||
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
|
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
|
||||||
priority_tag<2> /*unused*/)
|
priority_tag<2> /*unused*/)
|
||||||
@@ -6433,9 +6539,8 @@ auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, p
|
|||||||
void())
|
void())
|
||||||
{
|
{
|
||||||
ConstructibleArrayType ret;
|
ConstructibleArrayType ret;
|
||||||
const auto* inner_array = j.template get_ptr<const typename BasicJsonType::array_t*>();
|
reserve_if_possible(ret, j.size(), priority_tag<1> {});
|
||||||
reserve_if_possible(ret, inner_array->size(), priority_tag<1> {});
|
for (const auto& elem : array_elements(j))
|
||||||
for (const auto& elem : *inner_array)
|
|
||||||
{
|
{
|
||||||
// get<BasicJsonType>() returns *this, this won't call a from_json
|
// get<BasicJsonType>() returns *this, this won't call a from_json
|
||||||
// method when value_type is BasicJsonType
|
// method when value_type is BasicJsonType
|
||||||
@@ -6446,11 +6551,11 @@ auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, p
|
|||||||
|
|
||||||
template < typename BasicJsonType, typename ConstructibleArrayType,
|
template < typename BasicJsonType, typename ConstructibleArrayType,
|
||||||
enable_if_t <
|
enable_if_t <
|
||||||
is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
|
is_constructible_array_type<json_type_of_t<BasicJsonType>, ConstructibleArrayType>::value&&
|
||||||
!is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
|
!is_constructible_object_type<json_type_of_t<BasicJsonType>, ConstructibleArrayType>::value&&
|
||||||
!is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
|
!is_constructible_string_type<json_type_of_t<BasicJsonType>, ConstructibleArrayType>::value&&
|
||||||
!std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
|
!std::is_same<ConstructibleArrayType, typename json_type_of_t<BasicJsonType>::binary_t>::value&&
|
||||||
!is_compatible_binary_type<BasicJsonType, ConstructibleArrayType>::value&&
|
!is_compatible_binary_type<json_type_of_t<BasicJsonType>, ConstructibleArrayType>::value&&
|
||||||
!is_basic_json<ConstructibleArrayType>::value,
|
!is_basic_json<ConstructibleArrayType>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
|
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
|
||||||
@@ -6517,24 +6622,24 @@ auto from_json(const BasicJsonType& j, identity_tag<std::array<T, N>> tag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
|
inline void from_json(const BasicJsonType& j, typename json_type_of_t<BasicJsonType>::binary_t& bin)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("binary", j);
|
throw_type_must_be("binary", j);
|
||||||
}
|
}
|
||||||
|
|
||||||
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
|
bin = binary_value(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename CompatibleArrayType,
|
template < typename BasicJsonType, typename CompatibleArrayType,
|
||||||
enable_if_t < is_compatible_binary_type<BasicJsonType, CompatibleArrayType>::value,
|
enable_if_t < is_compatible_binary_type<json_type_of_t<BasicJsonType>, CompatibleArrayType>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
inline void from_json(const BasicJsonType& j, CompatibleArrayType& bin)
|
inline void from_json(const BasicJsonType& j, CompatibleArrayType& bin)
|
||||||
{
|
{
|
||||||
if (j.is_binary())
|
if (j.is_binary())
|
||||||
{
|
{
|
||||||
bin = static_cast<CompatibleArrayType>(*j.template get_ptr<const typename BasicJsonType::binary_t*>());
|
bin = static_cast<CompatibleArrayType>(binary_value(j));
|
||||||
}
|
}
|
||||||
else if (j.is_array())
|
else if (j.is_array())
|
||||||
{
|
{
|
||||||
@@ -6563,8 +6668,47 @@ void from_json_object_emplace(ConstructibleObjectType& obj, Key&& key, Value&& v
|
|||||||
obj.emplace(std::forward<Key>(key), std::forward<Value>(value));
|
obj.emplace(std::forward<Key>(key), std::forward<Value>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a member of a view's object: a later member with the same key replaces an
|
||||||
|
// earlier one, as parse() keeps the last value of a repeated key (containers
|
||||||
|
// without operator[] keep the first)
|
||||||
|
template<typename ConstructibleObjectType, typename Key, typename Value>
|
||||||
|
auto from_json_object_assign(ConstructibleObjectType& obj, Key&& key, Value&& value, priority_tag<1> /*unused*/)
|
||||||
|
-> decltype(obj[std::forward<Key>(key)] = std::forward<Value>(value), void())
|
||||||
|
{
|
||||||
|
obj[std::forward<Key>(key)] = std::forward<Value>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ConstructibleObjectType, typename Key, typename Value>
|
||||||
|
void from_json_object_assign(ConstructibleObjectType& obj, Key&& key, Value&& value, priority_tag<0> /*unused*/)
|
||||||
|
{
|
||||||
|
obj.emplace(std::forward<Key>(key), std::forward<Value>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename BasicJsonType, typename ConstructibleObjectType, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
|
void from_json_object_impl(const BasicJsonType& j, ConstructibleObjectType& ret)
|
||||||
|
{
|
||||||
|
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
|
||||||
|
reserve_if_possible(ret, inner_object->size(), priority_tag<1> {});
|
||||||
|
for (const auto& p : *inner_object)
|
||||||
|
{
|
||||||
|
from_json_object_emplace(ret, p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>(), priority_tag<1> {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename View, typename ConstructibleObjectType, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
void from_json_object_impl(const View& v, ConstructibleObjectType& ret)
|
||||||
|
{
|
||||||
|
using string_t = typename View::basic_json_type::object_t::key_type;
|
||||||
|
reserve_if_possible(ret, v.size(), priority_tag<1> {});
|
||||||
|
for (const auto item : v.items())
|
||||||
|
{
|
||||||
|
const auto key = item.key();
|
||||||
|
from_json_object_assign(ret, string_t(key.data(), key.size()), item.value().template get<typename ConstructibleObjectType::mapped_type>(), priority_tag<1> {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename ConstructibleObjectType,
|
template<typename BasicJsonType, typename ConstructibleObjectType,
|
||||||
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
|
enable_if_t<is_constructible_object_type<json_type_of_t<BasicJsonType>, ConstructibleObjectType>::value, int> = 0>
|
||||||
inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
|
||||||
@@ -6573,12 +6717,7 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ConstructibleObjectType ret;
|
ConstructibleObjectType ret;
|
||||||
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
|
from_json_object_impl(j, ret);
|
||||||
reserve_if_possible(ret, inner_object->size(), priority_tag<1> {});
|
|
||||||
for (const auto& p : *inner_object)
|
|
||||||
{
|
|
||||||
from_json_object_emplace(ret, p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>(), priority_tag<1> {});
|
|
||||||
}
|
|
||||||
obj = std::move(ret);
|
obj = std::move(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6587,10 +6726,10 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
|||||||
template < typename BasicJsonType, typename ArithmeticType,
|
template < typename BasicJsonType, typename ArithmeticType,
|
||||||
enable_if_t <
|
enable_if_t <
|
||||||
std::is_arithmetic<ArithmeticType>::value&&
|
std::is_arithmetic<ArithmeticType>::value&&
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
|
!std::is_same<ArithmeticType, typename json_type_of_t<BasicJsonType>::number_unsigned_t>::value&&
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
|
!std::is_same<ArithmeticType, typename json_type_of_t<BasicJsonType>::number_integer_t>::value&&
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
|
!std::is_same<ArithmeticType, typename json_type_of_t<BasicJsonType>::number_float_t>::value&&
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
!std::is_same<ArithmeticType, typename json_type_of_t<BasicJsonType>::boolean_t>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
inline void from_json(const BasicJsonType& j, ArithmeticType& val)
|
inline void from_json(const BasicJsonType& j, ArithmeticType& val)
|
||||||
{
|
{
|
||||||
@@ -6604,7 +6743,7 @@ inline void from_json(const BasicJsonType& j, ArithmeticType& val)
|
|||||||
{
|
{
|
||||||
throw_type_must_be("number", j);
|
throw_type_must_be("number", j);
|
||||||
}
|
}
|
||||||
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
|
val = static_cast<ArithmeticType>(boolean_value(j));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename Type>
|
template<typename BasicJsonType, typename Type>
|
||||||
@@ -6614,7 +6753,7 @@ detail::uncvref_t<Type> from_json_tuple_get_impl(BasicJsonType&& j, detail::iden
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename Type,
|
template<typename BasicJsonType, typename Type,
|
||||||
detail::enable_if_t<detail::is_compatible_reference_type<BasicJsonType, Type>::value, int> = 0>
|
detail::enable_if_t<conjunction<is_basic_json<uncvref_t<BasicJsonType>>, is_compatible_reference_type<BasicJsonType, Type>>::value, int> = 0>
|
||||||
Type from_json_tuple_get_impl(BasicJsonType && j, detail::identity_tag<Type> /*unused*/, detail::priority_tag<1> /*unused*/)
|
Type from_json_tuple_get_impl(BasicJsonType && j, detail::identity_tag<Type> /*unused*/, detail::priority_tag<1> /*unused*/)
|
||||||
{
|
{
|
||||||
return std::forward<BasicJsonType>(j).template get_ref<Type>();
|
return std::forward<BasicJsonType>(j).template get_ref<Type>();
|
||||||
@@ -6658,7 +6797,7 @@ inline void from_json_tuple_impl(const BasicJsonType& j, std::pair<A1, A2>& p, p
|
|||||||
template<typename BasicJsonType, typename... Args>
|
template<typename BasicJsonType, typename... Args>
|
||||||
std::tuple<Args...> from_json_tuple_impl(const BasicJsonType& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
|
std::tuple<Args...> from_json_tuple_impl(const BasicJsonType& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
|
||||||
{
|
{
|
||||||
static_assert(conjunction<disjunction<negation<std::is_reference<Args>>, is_compatible_reference_type<const BasicJsonType&, Args>>...>::value,
|
static_assert(conjunction<disjunction<negation<std::is_reference<Args>>, conjunction<is_basic_json<BasicJsonType>, is_compatible_reference_type<const BasicJsonType&, Args>>>...>::value,
|
||||||
"Can not return a tuple containing references to types not contained in a Json, try Json::get_to()");
|
"Can not return a tuple containing references to types not contained in a Json, try Json::get_to()");
|
||||||
return from_json_tuple_impl_base<1, Args...>(j, index_sequence_for<Args...> {});
|
return from_json_tuple_impl_base<1, Args...>(j, index_sequence_for<Args...> {});
|
||||||
}
|
}
|
||||||
@@ -6704,7 +6843,7 @@ void from_json_pair_array_to_map(const BasicJsonType& j, MapType& m)
|
|||||||
// read a map with enum keys from an object, using the enum's own from_json for
|
// read a map with enum keys from an object, using the enum's own from_json for
|
||||||
// the keys (e.g., from NLOHMANN_JSON_SERIALIZE_ENUM); this is the form written
|
// the keys (e.g., from NLOHMANN_JSON_SERIALIZE_ENUM); this is the form written
|
||||||
// with JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
// with JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||||
template<typename BasicJsonType, typename Map>
|
template < typename BasicJsonType, typename Map, enable_if_not_view_t<BasicJsonType> = 0 >
|
||||||
inline bool from_json_enum_keyed_object(const BasicJsonType& j, Map& m, std::true_type /*key is enum*/)
|
inline bool from_json_enum_keyed_object(const BasicJsonType& j, Map& m, std::true_type /*key is enum*/)
|
||||||
{
|
{
|
||||||
if (!j.is_object())
|
if (!j.is_object())
|
||||||
@@ -6719,6 +6858,24 @@ inline bool from_json_enum_keyed_object(const BasicJsonType& j, Map& m, std::tru
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename View, typename Map, enable_if_t<is_json_view<View>::value, int> = 0>
|
||||||
|
inline bool from_json_enum_keyed_object(const View& v, Map& m, std::true_type /*key is enum*/)
|
||||||
|
{
|
||||||
|
using json_t = typename View::basic_json_type;
|
||||||
|
if (!v.is_object())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m.clear();
|
||||||
|
for (const auto item : v.items())
|
||||||
|
{
|
||||||
|
const auto key = item.key();
|
||||||
|
from_json_object_assign(m, json_t(typename json_t::string_t(key.data(), key.size())).template get<typename Map::key_type>(),
|
||||||
|
item.value().template get<typename Map::mapped_type>(), priority_tag<1> {});
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename Map>
|
template<typename BasicJsonType, typename Map>
|
||||||
inline bool from_json_enum_keyed_object(const BasicJsonType& /*j*/, Map& /*m*/, std::false_type /*key is enum*/)
|
inline bool from_json_enum_keyed_object(const BasicJsonType& /*j*/, Map& /*m*/, std::false_type /*key is enum*/)
|
||||||
{
|
{
|
||||||
@@ -6727,7 +6884,7 @@ inline bool from_json_enum_keyed_object(const BasicJsonType& /*j*/, Map& /*m*/,
|
|||||||
|
|
||||||
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
|
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
|
||||||
typename = enable_if_t < !std::is_constructible <
|
typename = enable_if_t < !std::is_constructible <
|
||||||
typename BasicJsonType::string_t, Key >::value >>
|
typename json_type_of_t<BasicJsonType>::string_t, Key >::value >>
|
||||||
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
|
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(modernize-type-traits) we use C++11
|
// NOLINTNEXTLINE(modernize-type-traits) we use C++11
|
||||||
@@ -6740,7 +6897,7 @@ void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>&
|
|||||||
|
|
||||||
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
|
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
|
||||||
typename = enable_if_t < !std::is_constructible <
|
typename = enable_if_t < !std::is_constructible <
|
||||||
typename BasicJsonType::string_t, Key >::value >>
|
typename json_type_of_t<BasicJsonType>::string_t, Key >::value >>
|
||||||
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
|
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(modernize-type-traits) we use C++11
|
// NOLINTNEXTLINE(modernize-type-traits) we use C++11
|
||||||
@@ -6764,7 +6921,7 @@ inline void from_json(const BasicJsonType& j, std_fs::path& p)
|
|||||||
{
|
{
|
||||||
throw_type_must_be("string", j);
|
throw_type_must_be("string", j);
|
||||||
}
|
}
|
||||||
const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
const auto& s = string_value(j);
|
||||||
// Checking for C++20 standard or later can be insufficient in case the
|
// Checking for C++20 standard or later can be insufficient in case the
|
||||||
// library support for char8_t is either incomplete or was disabled
|
// library support for char8_t is either incomplete or was disabled
|
||||||
// altogether. Use the __cpp_lib_char8_t feature test instead.
|
// altogether. Use the __cpp_lib_char8_t feature test instead.
|
||||||
@@ -6803,10 +6960,9 @@ struct fn
|
|||||||
};
|
};
|
||||||
} // namespace from_json_adl
|
} // namespace from_json_adl
|
||||||
|
|
||||||
// the sources whose from_json() is only looked up by ADL: views (the library's
|
// the sources whose from_json() is only looked up by ADL: the probe
|
||||||
// overloads are written for basic_json) and the probe
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct is_adl_only_from_json_source : disjunction<is_json_view<T>, std::is_same<T, from_json_adl::probe>> {};
|
struct is_adl_only_from_json_source : std::is_same<T, from_json_adl::probe> {};
|
||||||
|
|
||||||
struct from_json_fn
|
struct from_json_fn
|
||||||
{
|
{
|
||||||
@@ -6857,20 +7013,6 @@ void from_json_base(const View& v, T& base)
|
|||||||
v.get_to(base);
|
v.get_to(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the context of an exception thrown by a from_json() of the macros: the value
|
|
||||||
// itself for basic_json (for JSON_DIAGNOSTICS), none for a view
|
|
||||||
template<typename BasicJsonType, enable_if_t<is_basic_json<BasicJsonType>::value, int> = 0>
|
|
||||||
const BasicJsonType * from_json_context(const BasicJsonType& j) noexcept
|
|
||||||
{
|
|
||||||
return &j;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename View, enable_if_t<is_json_view<View>::value, int> = 0>
|
|
||||||
std::nullptr_t from_json_context(const View& /*unused*/) noexcept
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// a value as an exception message shows it (invalid UTF-8 replaced; the
|
// a value as an exception message shows it (invalid UTF-8 replaced; the
|
||||||
// strings of a view are always valid UTF-8)
|
// strings of a view are always valid UTF-8)
|
||||||
template<typename BasicJsonType, enable_if_t<is_basic_json<BasicJsonType>::value, int> = 0>
|
template<typename BasicJsonType, enable_if_t<is_basic_json<BasicJsonType>::value, int> = 0>
|
||||||
|
|||||||
Generated
+17
-12
@@ -7797,14 +7797,16 @@ struct is_direct_value : std::integral_constant < bool,
|
|||||||
template<typename Traits, typename Alloc, typename BasicJsonType, typename View>
|
template<typename Traits, typename Alloc, typename BasicJsonType, typename View>
|
||||||
struct is_direct_value<std::basic_string<char, Traits, Alloc>, BasicJsonType, View> : std::true_type {};
|
struct is_direct_value<std::basic_string<char, Traits, Alloc>, BasicJsonType, View> : std::true_type {};
|
||||||
|
|
||||||
|
// (vectors of these, which are faster than through from_json(), and containers
|
||||||
|
// of views; other containers are read by the library's from_json())
|
||||||
template<typename U, typename A, typename BasicJsonType, typename View>
|
template<typename U, typename A, typename BasicJsonType, typename View>
|
||||||
struct is_direct_value<std::vector<U, A>, BasicJsonType, View> : std::true_type {};
|
struct is_direct_value<std::vector<U, A>, BasicJsonType, View> : is_direct_value<U, BasicJsonType, View> {};
|
||||||
|
|
||||||
template<typename K, typename V, typename C, typename A, typename BasicJsonType, typename View>
|
template<typename K, typename C, typename A, typename BasicJsonType, typename View>
|
||||||
struct is_direct_value<std::map<K, V, C, A>, BasicJsonType, View> : is_string_key<K> {};
|
struct is_direct_value<std::map<K, View, C, A>, BasicJsonType, View> : is_string_key<K> {};
|
||||||
|
|
||||||
template<typename K, typename V, typename H, typename E, typename A, typename BasicJsonType, typename View>
|
template<typename K, typename H, typename E, typename A, typename BasicJsonType, typename View>
|
||||||
struct is_direct_value<std::unordered_map<K, V, H, E, A>, BasicJsonType, View> : is_string_key<K> {};
|
struct is_direct_value<std::unordered_map<K, View, H, E, A>, BasicJsonType, View> : is_string_key<K> {};
|
||||||
|
|
||||||
} // namespace view
|
} // namespace view
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@@ -8637,22 +8639,25 @@ class basic_json_view
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename A>
|
/// vectors of the types converted directly (faster than the library's
|
||||||
|
/// from_json()) and containers of views (no from_json() reads them: a view
|
||||||
|
/// is no value of BasicJsonType); other containers are read by from_json()
|
||||||
|
template < typename U, typename A, typename std::enable_if < detail::view::is_direct_value<U, BasicJsonType, basic_json_view>::value, int >::type = 0 >
|
||||||
std::vector<U, A> get_impl(detail::view::value_tag<std::vector<U, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
|
std::vector<U, A> get_impl(detail::view::value_tag<std::vector<U, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
|
||||||
{
|
{
|
||||||
return detail::view::vector_value<basic_json_view, U, A>(*this);
|
return detail::view::vector_value<basic_json_view, U, A>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename K, typename V, typename C, typename A, typename std::enable_if<detail::view::is_string_key<K>::value, int>::type = 0>
|
template<typename K, typename C, typename A, typename std::enable_if<detail::view::is_string_key<K>::value, int>::type = 0>
|
||||||
std::map<K, V, C, A> get_impl(detail::view::value_tag<std::map<K, V, C, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
|
std::map<K, basic_json_view, C, A> get_impl(detail::view::value_tag<std::map<K, basic_json_view, C, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
|
||||||
{
|
{
|
||||||
return detail::view::map_value<std::map<K, V, C, A>>(*this);
|
return detail::view::map_value<std::map<K, basic_json_view, C, A>>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename K, typename V, typename H, typename E, typename A, typename std::enable_if<detail::view::is_string_key<K>::value, int>::type = 0>
|
template<typename K, typename H, typename E, typename A, typename std::enable_if<detail::view::is_string_key<K>::value, int>::type = 0>
|
||||||
std::unordered_map<K, V, H, E, A> get_impl(detail::view::value_tag<std::unordered_map<K, V, H, E, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
|
std::unordered_map<K, basic_json_view, H, E, A> get_impl(detail::view::value_tag<std::unordered_map<K, basic_json_view, H, E, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
|
||||||
{
|
{
|
||||||
return detail::view::map_value<std::unordered_map<K, V, H, E, A>>(*this);
|
return detail::view::map_value<std::unordered_map<K, basic_json_view, H, E, A>>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// whether the from_json() of T's serializer reads views (see
|
/// whether the from_json() of T's serializer reads views (see
|
||||||
|
|||||||
@@ -52,6 +52,11 @@ struct point
|
|||||||
int x = 0;
|
int x = 0;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(point, x, y)
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(point, x, y)
|
||||||
|
|
||||||
|
friend bool operator==(const point& a, const point& b)
|
||||||
|
{
|
||||||
|
return a.x == b.x && a.y == b.y;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct shape
|
struct shape
|
||||||
@@ -184,6 +189,13 @@ namespace
|
|||||||
{
|
{
|
||||||
template<typename T, typename View = json_view>
|
template<typename T, typename View = json_view>
|
||||||
struct reads_view : nlohmann::detail::has_view_from_json<nlohmann::adl_serializer<T, void>, View, T> {};
|
struct reads_view : nlohmann::detail::has_view_from_json<nlohmann::adl_serializer<T, void>, View, T> {};
|
||||||
|
|
||||||
|
// whether a member converts to the same T from the view and from the materialized value
|
||||||
|
template<typename T>
|
||||||
|
bool same(const json_view& v, const json& j, const char* key)
|
||||||
|
{
|
||||||
|
return v[key].get<T>() == j[key].get<T>();
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST_CASE("json_view from_json")
|
TEST_CASE("json_view from_json")
|
||||||
@@ -215,39 +227,119 @@ TEST_CASE("json_view from_json")
|
|||||||
static_assert(!nlohmann::is_json_view<int>::value, "is_json_view");
|
static_assert(!nlohmann::is_json_view<int>::value, "is_json_view");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("the library's own conversions are not called with a view (and the probe compiles for them)")
|
SECTION("the library's own conversions read views")
|
||||||
{
|
{
|
||||||
// these go through materialize() (vectors, maps with string keys,
|
static_assert(reads_view<std::list<int>>::value, "std types");
|
||||||
// strings, and numbers are converted by the view itself)
|
static_assert(reads_view<std::deque<point>>::value, "std types");
|
||||||
static_assert(!reads_view<std::list<int>>::value, "std types");
|
static_assert(reads_view<std::set<std::string>>::value, "std types");
|
||||||
static_assert(!reads_view<std::deque<point>>::value, "std types");
|
static_assert(reads_view<std::unordered_set<int>>::value, "std types");
|
||||||
static_assert(!reads_view<std::set<std::string>>::value, "std types");
|
static_assert(reads_view<std::forward_list<int>>::value, "std types");
|
||||||
static_assert(!reads_view<std::unordered_set<int>>::value, "std types");
|
static_assert(reads_view<std::valarray<double>>::value, "std types");
|
||||||
static_assert(!reads_view<std::forward_list<int>>::value, "std types");
|
static_assert(reads_view<std::array<int, 3>>::value, "std types");
|
||||||
static_assert(!reads_view<std::valarray<double>>::value, "std types");
|
static_assert(reads_view<std::pair<int, std::string>>::value, "std types");
|
||||||
static_assert(!reads_view<std::array<int, 3>>::value, "std types");
|
static_assert(reads_view<std::tuple<int, bool, point>>::value, "std types");
|
||||||
static_assert(!reads_view<std::pair<int, std::string>>::value, "std types");
|
static_assert(reads_view<std::map<int, int>>::value, "std types");
|
||||||
static_assert(!reads_view<std::tuple<int, bool, point>>::value, "std types");
|
static_assert(reads_view<std::unordered_map<int, point>>::value, "std types");
|
||||||
static_assert(!reads_view<std::map<int, int>>::value, "std types");
|
static_assert(reads_view<std::map<color, int>>::value, "std types");
|
||||||
static_assert(!reads_view<std::unordered_map<int, point>>::value, "std types");
|
static_assert(reads_view<std::map<std::string, int>>::value, "std types");
|
||||||
static_assert(!reads_view<std::map<color, int>>::value, "std types");
|
static_assert(reads_view<std::vector<point>>::value, "std types");
|
||||||
static_assert(!reads_view<std::map<std::string, int>>::value, "std types");
|
static_assert(reads_view<std::vector<bool>>::value, "std types");
|
||||||
static_assert(!reads_view<std::vector<point>>::value, "std types");
|
static_assert(reads_view<std::vector<std::uint8_t>>::value, "std types");
|
||||||
static_assert(!reads_view<std::vector<bool>>::value, "std types");
|
static_assert(reads_view<std::string>::value, "std types");
|
||||||
static_assert(!reads_view<std::vector<std::uint8_t>>::value, "std types");
|
static_assert(reads_view<int>::value, "std types");
|
||||||
static_assert(!reads_view<std::string>::value, "std types");
|
static_assert(reads_view<bool>::value, "std types");
|
||||||
static_assert(!reads_view<int>::value, "std types");
|
static_assert(reads_view<double>::value, "std types");
|
||||||
static_assert(!reads_view<bool>::value, "std types");
|
static_assert(reads_view<std::nullptr_t>::value, "std types");
|
||||||
static_assert(!reads_view<double>::value, "std types");
|
static_assert(!reads_view<json>::value, "get<BasicJsonType>() is materialize()");
|
||||||
static_assert(!reads_view<std::nullptr_t>::value, "std types");
|
static_assert(reads_view<json::binary_t>::value, "std types");
|
||||||
static_assert(!reads_view<json>::value, "std types");
|
|
||||||
static_assert(!reads_view<json::binary_t>::value, "std types");
|
|
||||||
#ifdef JSON_HAS_CPP_17
|
#ifdef JSON_HAS_CPP_17
|
||||||
static_assert(!reads_view<std::optional<point>>::value, "std types");
|
static_assert(reads_view<std::optional<point>>::value, "std types");
|
||||||
#endif
|
#endif
|
||||||
CHECK(true);
|
CHECK(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("std types: the same values as from the materialized value")
|
||||||
|
{
|
||||||
|
const json_document d = json_document::parse(R"({"ints": [3, 1, 2, 1], "strings": ["b", "a", "b"], "pairs": [[1, "x"], [2, "y"]],
|
||||||
|
"points": [{"x": 1, "y": 2}, {"x": 3, "y": 4}], "object": {"b": 1, "a": 2}, "triple": [1, true, {"x": 5, "y": 6}],
|
||||||
|
"colors": {"green": 1, "red": 2}, "bytes": [1, 2, 255], "nested": [[1, 2], [3]], "number": 1.5, "flag": true,
|
||||||
|
"text": "hello", "nothing": null, "mixed": [1, 2.5, -3, 4], "flags": [true, false, true]})");
|
||||||
|
const json j = d.root().materialize();
|
||||||
|
const json_view v = d.root();
|
||||||
|
CHECK(same<std::list<int>>(v, j, "ints"));
|
||||||
|
CHECK(same<std::deque<int>>(v, j, "ints"));
|
||||||
|
CHECK(same<std::set<int>>(v, j, "ints"));
|
||||||
|
CHECK(same<std::multiset<int>>(v, j, "ints"));
|
||||||
|
CHECK(same<std::unordered_set<std::string>>(v, j, "strings"));
|
||||||
|
CHECK(same<std::forward_list<int>>(v, j, "ints"));
|
||||||
|
CHECK(same<std::array<int, 4>>(v, j, "ints"));
|
||||||
|
CHECK(same<std::array<double, 4>>(v, j, "mixed"));
|
||||||
|
CHECK((v["pairs"][0].get<std::pair<int, std::string>>() == j["pairs"][0].get<std::pair<int, std::string>>()));
|
||||||
|
CHECK(same<std::vector<std::pair<int, std::string>>>(v, j, "pairs"));
|
||||||
|
CHECK(same<std::tuple<int, bool, point>>(v, j, "triple"));
|
||||||
|
CHECK(same<std::map<int, std::string>>(v, j, "pairs"));
|
||||||
|
CHECK(same<std::unordered_map<int, std::string>>(v, j, "pairs"));
|
||||||
|
CHECK(same<std::map<std::string, int>>(v, j, "object"));
|
||||||
|
CHECK(same<std::unordered_map<std::string, int>>(v, j, "object"));
|
||||||
|
CHECK(same<std::map<color, int>>(v, j, "colors"));
|
||||||
|
CHECK(same<std::vector<point>>(v, j, "points"));
|
||||||
|
CHECK(same<std::vector<int>>(v, j, "ints"));
|
||||||
|
CHECK(same<std::vector<bool>>(v, j, "flags"));
|
||||||
|
CHECK(same<std::vector<std::uint8_t>>(v, j, "bytes"));
|
||||||
|
CHECK(same<std::vector<std::vector<int>>>(v, j, "nested"));
|
||||||
|
CHECK(same<std::vector<json>>(v, j, "mixed"));
|
||||||
|
CHECK(same<double>(v, j, "number"));
|
||||||
|
CHECK(same<bool>(v, j, "flag"));
|
||||||
|
CHECK(same<std::string>(v, j, "text"));
|
||||||
|
CHECK(same<std::nullptr_t>(v, j, "nothing"));
|
||||||
|
CHECK(same<json>(v, j, "object"));
|
||||||
|
const std::valarray<int> va = v["ints"].get<std::valarray<int>>();
|
||||||
|
CHECK(va.size() == 4);
|
||||||
|
CHECK(va[0] == 3);
|
||||||
|
int c_array[2][2] = {{0, 0}, {0, 0}}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): the conversion to C arrays
|
||||||
|
v["nested"][0].get_to(c_array[0]);
|
||||||
|
CHECK(c_array[0][1] == 2);
|
||||||
|
#ifdef JSON_HAS_CPP_17
|
||||||
|
CHECK(v["points"][0].get<std::optional<point>>()->y == 2);
|
||||||
|
CHECK(!v["nothing"].get<std::optional<point>>().has_value());
|
||||||
|
#endif
|
||||||
|
// containers of views keep views of the elements
|
||||||
|
const std::vector<json_view> views = v["points"].get<std::vector<json_view>>();
|
||||||
|
CHECK(views.size() == 2);
|
||||||
|
CHECK(views[1]["x"].get<int>() == 3);
|
||||||
|
CHECK(v["object"].get<std::map<std::string, json_view>>().at("a").get<int>() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("std types: duplicate keys keep the last value, as from the materialized value")
|
||||||
|
{
|
||||||
|
const json_document d = json_document::parse(R"({"a": 1, "b": 2, "a": 3})");
|
||||||
|
CHECK((d.root().get<std::map<std::string, int>>() == d.root().materialize().get<std::map<std::string, int>>()));
|
||||||
|
CHECK(d.root().get<std::map<std::string, int>>().at("a") == 3);
|
||||||
|
CHECK(d.root().get<std::unordered_map<std::string, int>>().at("a") == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(JSON_NOEXCEPTION) && !JSON_DIAGNOSTICS
|
||||||
|
SECTION("std types: the same errors as from the materialized value")
|
||||||
|
{
|
||||||
|
const json_document d = json_document::parse(R"([[1, "x"], {"a": 1}, "text", [1], 5, null])");
|
||||||
|
const json j = d.root().materialize();
|
||||||
|
for (std::size_t i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
CAPTURE(i)
|
||||||
|
const json_view v = d.root()[i];
|
||||||
|
CHECK(exception_of_call([&] { static_cast<void>(v.get<std::list<int>>()); }) == exception_of_call([&] { static_cast<void>(j[i].get<std::list<int>>()); }));
|
||||||
|
CHECK(exception_of_call([&] { static_cast<void>(v.get<std::forward_list<int>>()); }) == exception_of_call([&] { static_cast<void>(j[i].get<std::forward_list<int>>()); }));
|
||||||
|
CHECK(exception_of_call([&] { static_cast<void>(v.get<std::array<int, 2>>()); }) == exception_of_call([&] { static_cast<void>(j[i].get<std::array<int, 2>>()); }));
|
||||||
|
CHECK(exception_of_call([&] { static_cast<void>(v.get<std::pair<int, std::string>>()); }) == exception_of_call([&] { static_cast<void>(j[i].get<std::pair<int, std::string>>()); }));
|
||||||
|
CHECK(exception_of_call([&] { static_cast<void>(v.get<std::map<std::string, int>>()); }) == exception_of_call([&] { static_cast<void>(j[i].get<std::map<std::string, int>>()); }));
|
||||||
|
CHECK(exception_of_call([&] { static_cast<void>(v.get<std::map<int, int>>()); }) == exception_of_call([&] { static_cast<void>(j[i].get<std::map<int, int>>()); }));
|
||||||
|
CHECK(exception_of_call([&] { static_cast<void>(v.get<std::vector<std::uint8_t>>()); }) == exception_of_call([&] { static_cast<void>(j[i].get<std::vector<std::uint8_t>>()); }));
|
||||||
|
CHECK(exception_of_call([&] { static_cast<void>(v.get<json::binary_t>()); }) == exception_of_call([&] { static_cast<void>(j[i].get<json::binary_t>()); }));
|
||||||
|
CHECK(exception_of_call([&] { static_cast<void>(v.get<std::valarray<int>>()); }) == exception_of_call([&] { static_cast<void>(j[i].get<std::valarray<int>>()); }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SECTION("macro types")
|
SECTION("macro types")
|
||||||
{
|
{
|
||||||
const json_document d = json_document::parse(R"({"name": "s", "points": [{"x": 1, "y": 2}, {"x": 3, "y": 4}],
|
const json_document d = json_document::parse(R"({"name": "s", "points": [{"x": 1, "y": 2}, {"x": 3, "y": 4}],
|
||||||
|
|||||||
Reference in new issue
Block a user