mirror of
https://github.com/nlohmann/json
synced 2024-11-25 13:20:05 +00:00
Reimplement value() access functions (#3663)
* Reimplement value() access functions * Merges the 'const char *' with the 'ValueType &&' overloads. * Fixes ambiguities when default value is 0. * Fixes 'no matching function' error when specifying ValueType template parameter. * Fixes incorrect template parameter order in previous overloads. * Add additional value() tests * Make JSON_MultipleHeaders visible to unit tests Define the macro JSON_TEST_USING_MULTIPLE_HEADERS to 0/1 depending on JSON_MultipleHeaders. * Add type_traits unit test * Update documentation
This commit is contained in:
parent
8eee62d388
commit
0c7a18374c
@ -7,7 +7,7 @@ ValueType value(const typename object_t::key_type& key,
|
|||||||
ValueType&& default_value) const;
|
ValueType&& default_value) const;
|
||||||
|
|
||||||
// (2)
|
// (2)
|
||||||
template<class KeyType, class ValueType>
|
template<class ValueType, class KeyType>
|
||||||
ValueType value(KeyType&& key,
|
ValueType value(KeyType&& key,
|
||||||
ValueType&& default_value) const;
|
ValueType&& default_value) const;
|
||||||
|
|
||||||
@ -155,5 +155,5 @@ changes to any JSON value.
|
|||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
1. Added in version 1.0.0. Changed parameter `default_value` type from `const ValueType&` to `ValueType&&` in version 3.11.0.
|
1. Added in version 1.0.0. Changed parameter `default_value` type from `const ValueType&` to `ValueType&&` in version 3.11.0.
|
||||||
2. Added in version 3.11.0.
|
2. Added in version 3.11.0. Made `ValueType` the first template parameter in version 3.11.2.
|
||||||
3. Added in version 2.0.2.
|
3. Added in version 2.0.2.
|
||||||
|
@ -684,5 +684,57 @@ inline constexpr bool value_in_range_of(T val)
|
|||||||
return value_in_range_of_impl1<OfType, T>::test(val);
|
return value_in_range_of_impl1<OfType, T>::test(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<bool Value>
|
||||||
|
using bool_constant = std::integral_constant<bool, Value>;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// is_c_string
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace impl
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr bool is_c_string()
|
||||||
|
{
|
||||||
|
using TUnExt = typename std::remove_extent<T>::type;
|
||||||
|
using TUnCVExt = typename std::remove_cv<TUnExt>::type;
|
||||||
|
using TUnPtr = typename std::remove_pointer<T>::type;
|
||||||
|
using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
|
||||||
|
return
|
||||||
|
(std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
|
||||||
|
|| (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace impl
|
||||||
|
|
||||||
|
// checks whether T is a [cv] char */[cv] char[] C string
|
||||||
|
template<typename T>
|
||||||
|
struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// is_transparent
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace impl
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr bool is_transparent()
|
||||||
|
{
|
||||||
|
return is_detected<detect_is_transparent, T>::value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace impl
|
||||||
|
|
||||||
|
// checks whether T has a member named is_transparent
|
||||||
|
template<typename T>
|
||||||
|
struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
@ -2194,14 +2194,24 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
|
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<typename KeyType>
|
||||||
|
using is_comparable_with_object_key = detail::is_comparable <
|
||||||
|
object_comparator_t, const typename object_t::key_type&, KeyType >;
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
using value_return_type = std::conditional <
|
||||||
|
detail::is_c_string_uncvref<ValueType>::value,
|
||||||
|
string_t, typename std::decay<ValueType>::type >;
|
||||||
|
|
||||||
|
public:
|
||||||
/// @brief access specified object element with default value
|
/// @brief access specified object element with default value
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||||
// this is the value(const typename object_t::key_type&) overload
|
template < class ValueType, detail::enable_if_t <
|
||||||
template < class KeyType, class ValueType, detail::enable_if_t <
|
!detail::is_transparent<object_comparator_t>::value
|
||||||
std::is_same<KeyType, typename object_t::key_type>::value
|
|
||||||
&& detail::is_getable<basic_json_t, ValueType>::value
|
&& detail::is_getable<basic_json_t, ValueType>::value
|
||||||
&& !std::is_same<value_t, ValueType>::value, int > = 0 >
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
typename std::decay<ValueType>::type value(const KeyType& key, ValueType && default_value) const
|
ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
|
||||||
{
|
{
|
||||||
// value only works for objects
|
// value only works for objects
|
||||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||||
@ -2210,7 +2220,32 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
const auto it = find(key);
|
const auto it = find(key);
|
||||||
if (it != end())
|
if (it != end())
|
||||||
{
|
{
|
||||||
return it->template get<typename std::decay<ValueType>::type>();
|
return it->template get<ValueType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief access specified object element with default value
|
||||||
|
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||||
|
template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
|
||||||
|
detail::enable_if_t <
|
||||||
|
!detail::is_transparent<object_comparator_t>::value
|
||||||
|
&& detail::is_getable<basic_json_t, ReturnType>::value
|
||||||
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
|
ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
|
||||||
|
{
|
||||||
|
// value only works for objects
|
||||||
|
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||||
|
{
|
||||||
|
// if key is found, return value and given default value otherwise
|
||||||
|
const auto it = find(key);
|
||||||
|
if (it != end())
|
||||||
|
{
|
||||||
|
return it->template get<ReturnType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::forward<ValueType>(default_value);
|
return std::forward<ValueType>(default_value);
|
||||||
@ -2221,36 +2256,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief access specified object element with default value
|
/// @brief access specified object element with default value
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||||
/// overload for a default value of type const char*
|
template < class ValueType, class KeyType, detail::enable_if_t <
|
||||||
string_t value(const typename object_t::key_type& key, const char* default_value) const
|
detail::is_transparent<object_comparator_t>::value
|
||||||
{
|
&& !detail::is_json_pointer<KeyType>::value
|
||||||
return value(key, string_t(default_value));
|
&& is_comparable_with_object_key<KeyType>::value
|
||||||
}
|
&& detail::is_getable<basic_json_t, ValueType>::value
|
||||||
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
// these two functions, in conjunction with value(const KeyType &, ValueType &&),
|
ValueType value(KeyType && key, const ValueType& default_value) const
|
||||||
// resolve an ambiguity that would otherwise occur between the json_pointer and
|
|
||||||
// typename object_t::key_type & overloads
|
|
||||||
template < class ValueType, detail::enable_if_t <
|
|
||||||
detail::is_getable<basic_json_t, ValueType>::value
|
|
||||||
&& !std::is_same<value_t, ValueType>::value, int > = 0 >
|
|
||||||
typename std::decay<ValueType>::type value(const char* key, ValueType && default_value) const
|
|
||||||
{
|
|
||||||
return value(typename object_t::key_type(key), std::forward<ValueType>(default_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
string_t value(const char* key, const char* default_value) const
|
|
||||||
{
|
|
||||||
return value(typename object_t::key_type(key), string_t(default_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief access specified object element with default value
|
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
|
||||||
/// using std::is_convertible in a std::enable_if will fail when using explicit conversions
|
|
||||||
template < class KeyType, class ValueType, detail::enable_if_t <
|
|
||||||
detail::is_getable<basic_json_t, ValueType>::value
|
|
||||||
&& !std::is_same<value_t, ValueType>::value
|
|
||||||
&& detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
|
||||||
typename std::decay<ValueType>::type value(KeyType && key, ValueType && default_value) const
|
|
||||||
{
|
{
|
||||||
// value only works for objects
|
// value only works for objects
|
||||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||||
@ -2259,7 +2271,34 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
const auto it = find(std::forward<KeyType>(key));
|
const auto it = find(std::forward<KeyType>(key));
|
||||||
if (it != end())
|
if (it != end())
|
||||||
{
|
{
|
||||||
return it->template get<typename std::decay<ValueType>::type>();
|
return it->template get<ValueType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief access specified object element via JSON Pointer with default value
|
||||||
|
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||||
|
template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
|
||||||
|
detail::enable_if_t <
|
||||||
|
detail::is_transparent<object_comparator_t>::value
|
||||||
|
&& !detail::is_json_pointer<KeyType>::value
|
||||||
|
&& is_comparable_with_object_key<KeyType>::value
|
||||||
|
&& detail::is_getable<basic_json_t, ReturnType>::value
|
||||||
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
|
ReturnType value(KeyType && key, ValueType && default_value) const
|
||||||
|
{
|
||||||
|
// value only works for objects
|
||||||
|
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||||
|
{
|
||||||
|
// if key is found, return value and given default value otherwise
|
||||||
|
const auto it = find(std::forward<KeyType>(key));
|
||||||
|
if (it != end())
|
||||||
|
{
|
||||||
|
return it->template get<ReturnType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::forward<ValueType>(default_value);
|
return std::forward<ValueType>(default_value);
|
||||||
@ -2268,20 +2307,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief access specified object element with default value
|
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
|
||||||
/// overload for a default value of type const char*
|
|
||||||
template < class KeyType, detail::enable_if_t <
|
|
||||||
!detail::is_json_pointer<KeyType>::value, int > = 0 >
|
|
||||||
string_t value(KeyType && key, const char* default_value) const
|
|
||||||
{
|
|
||||||
return value(std::forward<KeyType>(key), string_t(default_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief access specified object element via JSON Pointer with default value
|
/// @brief access specified object element via JSON Pointer with default value
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||||
template < class ValueType, detail::enable_if_t <
|
template < class ValueType, detail::enable_if_t <
|
||||||
detail::is_getable<basic_json_t, ValueType>::value, int> = 0 >
|
detail::is_getable<basic_json_t, ValueType>::value
|
||||||
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
ValueType value(const json_pointer& ptr, const ValueType& default_value) const
|
ValueType value(const json_pointer& ptr, const ValueType& default_value) const
|
||||||
{
|
{
|
||||||
// value only works for objects
|
// value only works for objects
|
||||||
@ -2301,29 +2331,50 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief access specified object element via JSON Pointer with default value
|
||||||
|
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||||
|
template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
|
||||||
|
detail::enable_if_t <
|
||||||
|
detail::is_getable<basic_json_t, ReturnType>::value
|
||||||
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
|
ReturnType value(const json_pointer& ptr, ValueType && default_value) const
|
||||||
|
{
|
||||||
|
// value only works for objects
|
||||||
|
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||||
|
{
|
||||||
|
// if pointer resolves a value, return it or use default value
|
||||||
|
JSON_TRY
|
||||||
|
{
|
||||||
|
return ptr.get_checked(this).template get<ReturnType>();
|
||||||
|
}
|
||||||
|
JSON_INTERNAL_CATCH (out_of_range&)
|
||||||
|
{
|
||||||
|
return std::forward<ValueType>(default_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||||
|
}
|
||||||
|
|
||||||
template < class ValueType, class BasicJsonType, detail::enable_if_t <
|
template < class ValueType, class BasicJsonType, detail::enable_if_t <
|
||||||
detail::is_getable<basic_json_t, ValueType>::value, int> = 0 >
|
detail::is_basic_json<BasicJsonType>::value
|
||||||
|
&& detail::is_getable<basic_json_t, ValueType>::value
|
||||||
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
||||||
ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
|
ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
|
||||||
{
|
{
|
||||||
return value(ptr.convert(), default_value);
|
return value(ptr.convert(), default_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief access specified object element via JSON Pointer with default value
|
template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
detail::enable_if_t <
|
||||||
/// overload for a default value of type const char*
|
detail::is_basic_json<BasicJsonType>::value
|
||||||
JSON_HEDLEY_NON_NULL(3)
|
&& detail::is_getable<basic_json_t, ReturnType>::value
|
||||||
string_t value(const json_pointer& ptr, const char* default_value) const
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
{
|
|
||||||
return value(ptr, string_t(default_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
|
||||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
||||||
JSON_HEDLEY_NON_NULL(3)
|
ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
|
||||||
string_t value(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr, const char* default_value) const
|
|
||||||
{
|
{
|
||||||
return value(ptr.convert(), default_value);
|
return value(ptr.convert(), std::forward<ValueType>(default_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief access the first element
|
/// @brief access the first element
|
||||||
|
@ -4059,6 +4059,58 @@ inline constexpr bool value_in_range_of(T val)
|
|||||||
return value_in_range_of_impl1<OfType, T>::test(val);
|
return value_in_range_of_impl1<OfType, T>::test(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<bool Value>
|
||||||
|
using bool_constant = std::integral_constant<bool, Value>;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// is_c_string
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace impl
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr bool is_c_string()
|
||||||
|
{
|
||||||
|
using TUnExt = typename std::remove_extent<T>::type;
|
||||||
|
using TUnCVExt = typename std::remove_cv<TUnExt>::type;
|
||||||
|
using TUnPtr = typename std::remove_pointer<T>::type;
|
||||||
|
using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
|
||||||
|
return
|
||||||
|
(std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
|
||||||
|
|| (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace impl
|
||||||
|
|
||||||
|
// checks whether T is a [cv] char */[cv] char[] C string
|
||||||
|
template<typename T>
|
||||||
|
struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// is_transparent
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace impl
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr bool is_transparent()
|
||||||
|
{
|
||||||
|
return is_detected<detect_is_transparent, T>::value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace impl
|
||||||
|
|
||||||
|
// checks whether T has a member named is_transparent
|
||||||
|
template<typename T>
|
||||||
|
struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
@ -21274,14 +21326,24 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
|
JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<typename KeyType>
|
||||||
|
using is_comparable_with_object_key = detail::is_comparable <
|
||||||
|
object_comparator_t, const typename object_t::key_type&, KeyType >;
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
using value_return_type = std::conditional <
|
||||||
|
detail::is_c_string_uncvref<ValueType>::value,
|
||||||
|
string_t, typename std::decay<ValueType>::type >;
|
||||||
|
|
||||||
|
public:
|
||||||
/// @brief access specified object element with default value
|
/// @brief access specified object element with default value
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||||
// this is the value(const typename object_t::key_type&) overload
|
template < class ValueType, detail::enable_if_t <
|
||||||
template < class KeyType, class ValueType, detail::enable_if_t <
|
!detail::is_transparent<object_comparator_t>::value
|
||||||
std::is_same<KeyType, typename object_t::key_type>::value
|
|
||||||
&& detail::is_getable<basic_json_t, ValueType>::value
|
&& detail::is_getable<basic_json_t, ValueType>::value
|
||||||
&& !std::is_same<value_t, ValueType>::value, int > = 0 >
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
typename std::decay<ValueType>::type value(const KeyType& key, ValueType && default_value) const
|
ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
|
||||||
{
|
{
|
||||||
// value only works for objects
|
// value only works for objects
|
||||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||||
@ -21290,7 +21352,32 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
const auto it = find(key);
|
const auto it = find(key);
|
||||||
if (it != end())
|
if (it != end())
|
||||||
{
|
{
|
||||||
return it->template get<typename std::decay<ValueType>::type>();
|
return it->template get<ValueType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief access specified object element with default value
|
||||||
|
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||||
|
template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
|
||||||
|
detail::enable_if_t <
|
||||||
|
!detail::is_transparent<object_comparator_t>::value
|
||||||
|
&& detail::is_getable<basic_json_t, ReturnType>::value
|
||||||
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
|
ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
|
||||||
|
{
|
||||||
|
// value only works for objects
|
||||||
|
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||||
|
{
|
||||||
|
// if key is found, return value and given default value otherwise
|
||||||
|
const auto it = find(key);
|
||||||
|
if (it != end())
|
||||||
|
{
|
||||||
|
return it->template get<ReturnType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::forward<ValueType>(default_value);
|
return std::forward<ValueType>(default_value);
|
||||||
@ -21301,36 +21388,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
|
|
||||||
/// @brief access specified object element with default value
|
/// @brief access specified object element with default value
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||||
/// overload for a default value of type const char*
|
template < class ValueType, class KeyType, detail::enable_if_t <
|
||||||
string_t value(const typename object_t::key_type& key, const char* default_value) const
|
detail::is_transparent<object_comparator_t>::value
|
||||||
{
|
&& !detail::is_json_pointer<KeyType>::value
|
||||||
return value(key, string_t(default_value));
|
&& is_comparable_with_object_key<KeyType>::value
|
||||||
}
|
&& detail::is_getable<basic_json_t, ValueType>::value
|
||||||
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
// these two functions, in conjunction with value(const KeyType &, ValueType &&),
|
ValueType value(KeyType && key, const ValueType& default_value) const
|
||||||
// resolve an ambiguity that would otherwise occur between the json_pointer and
|
|
||||||
// typename object_t::key_type & overloads
|
|
||||||
template < class ValueType, detail::enable_if_t <
|
|
||||||
detail::is_getable<basic_json_t, ValueType>::value
|
|
||||||
&& !std::is_same<value_t, ValueType>::value, int > = 0 >
|
|
||||||
typename std::decay<ValueType>::type value(const char* key, ValueType && default_value) const
|
|
||||||
{
|
|
||||||
return value(typename object_t::key_type(key), std::forward<ValueType>(default_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
string_t value(const char* key, const char* default_value) const
|
|
||||||
{
|
|
||||||
return value(typename object_t::key_type(key), string_t(default_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief access specified object element with default value
|
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
|
||||||
/// using std::is_convertible in a std::enable_if will fail when using explicit conversions
|
|
||||||
template < class KeyType, class ValueType, detail::enable_if_t <
|
|
||||||
detail::is_getable<basic_json_t, ValueType>::value
|
|
||||||
&& !std::is_same<value_t, ValueType>::value
|
|
||||||
&& detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
|
||||||
typename std::decay<ValueType>::type value(KeyType && key, ValueType && default_value) const
|
|
||||||
{
|
{
|
||||||
// value only works for objects
|
// value only works for objects
|
||||||
if (JSON_HEDLEY_LIKELY(is_object()))
|
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||||
@ -21339,7 +21403,34 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
const auto it = find(std::forward<KeyType>(key));
|
const auto it = find(std::forward<KeyType>(key));
|
||||||
if (it != end())
|
if (it != end())
|
||||||
{
|
{
|
||||||
return it->template get<typename std::decay<ValueType>::type>();
|
return it->template get<ValueType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief access specified object element via JSON Pointer with default value
|
||||||
|
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||||
|
template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
|
||||||
|
detail::enable_if_t <
|
||||||
|
detail::is_transparent<object_comparator_t>::value
|
||||||
|
&& !detail::is_json_pointer<KeyType>::value
|
||||||
|
&& is_comparable_with_object_key<KeyType>::value
|
||||||
|
&& detail::is_getable<basic_json_t, ReturnType>::value
|
||||||
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
|
ReturnType value(KeyType && key, ValueType && default_value) const
|
||||||
|
{
|
||||||
|
// value only works for objects
|
||||||
|
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||||
|
{
|
||||||
|
// if key is found, return value and given default value otherwise
|
||||||
|
const auto it = find(std::forward<KeyType>(key));
|
||||||
|
if (it != end())
|
||||||
|
{
|
||||||
|
return it->template get<ReturnType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::forward<ValueType>(default_value);
|
return std::forward<ValueType>(default_value);
|
||||||
@ -21348,20 +21439,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief access specified object element with default value
|
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
|
||||||
/// overload for a default value of type const char*
|
|
||||||
template < class KeyType, detail::enable_if_t <
|
|
||||||
!detail::is_json_pointer<KeyType>::value, int > = 0 >
|
|
||||||
string_t value(KeyType && key, const char* default_value) const
|
|
||||||
{
|
|
||||||
return value(std::forward<KeyType>(key), string_t(default_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief access specified object element via JSON Pointer with default value
|
/// @brief access specified object element via JSON Pointer with default value
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||||
template < class ValueType, detail::enable_if_t <
|
template < class ValueType, detail::enable_if_t <
|
||||||
detail::is_getable<basic_json_t, ValueType>::value, int> = 0 >
|
detail::is_getable<basic_json_t, ValueType>::value
|
||||||
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
ValueType value(const json_pointer& ptr, const ValueType& default_value) const
|
ValueType value(const json_pointer& ptr, const ValueType& default_value) const
|
||||||
{
|
{
|
||||||
// value only works for objects
|
// value only works for objects
|
||||||
@ -21381,29 +21463,50 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief access specified object element via JSON Pointer with default value
|
||||||
|
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||||
|
template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
|
||||||
|
detail::enable_if_t <
|
||||||
|
detail::is_getable<basic_json_t, ReturnType>::value
|
||||||
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
|
ReturnType value(const json_pointer& ptr, ValueType && default_value) const
|
||||||
|
{
|
||||||
|
// value only works for objects
|
||||||
|
if (JSON_HEDLEY_LIKELY(is_object()))
|
||||||
|
{
|
||||||
|
// if pointer resolves a value, return it or use default value
|
||||||
|
JSON_TRY
|
||||||
|
{
|
||||||
|
return ptr.get_checked(this).template get<ReturnType>();
|
||||||
|
}
|
||||||
|
JSON_INTERNAL_CATCH (out_of_range&)
|
||||||
|
{
|
||||||
|
return std::forward<ValueType>(default_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||||
|
}
|
||||||
|
|
||||||
template < class ValueType, class BasicJsonType, detail::enable_if_t <
|
template < class ValueType, class BasicJsonType, detail::enable_if_t <
|
||||||
detail::is_getable<basic_json_t, ValueType>::value, int> = 0 >
|
detail::is_basic_json<BasicJsonType>::value
|
||||||
|
&& detail::is_getable<basic_json_t, ValueType>::value
|
||||||
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
||||||
ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
|
ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
|
||||||
{
|
{
|
||||||
return value(ptr.convert(), default_value);
|
return value(ptr.convert(), default_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief access specified object element via JSON Pointer with default value
|
template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
detail::enable_if_t <
|
||||||
/// overload for a default value of type const char*
|
detail::is_basic_json<BasicJsonType>::value
|
||||||
JSON_HEDLEY_NON_NULL(3)
|
&& detail::is_getable<basic_json_t, ReturnType>::value
|
||||||
string_t value(const json_pointer& ptr, const char* default_value) const
|
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||||
{
|
|
||||||
return value(ptr, string_t(default_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
|
||||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
|
||||||
JSON_HEDLEY_NON_NULL(3)
|
ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
|
||||||
string_t value(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr, const char* default_value) const
|
|
||||||
{
|
{
|
||||||
return value(ptr.convert(), default_value);
|
return value(ptr.convert(), std::forward<ValueType>(default_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief access the first element
|
/// @brief access the first element
|
||||||
|
@ -37,7 +37,8 @@ endif()
|
|||||||
add_library(test_main OBJECT src/unit.cpp)
|
add_library(test_main OBJECT src/unit.cpp)
|
||||||
target_compile_definitions(test_main PUBLIC
|
target_compile_definitions(test_main PUBLIC
|
||||||
DOCTEST_CONFIG_SUPER_FAST_ASSERTS
|
DOCTEST_CONFIG_SUPER_FAST_ASSERTS
|
||||||
JSON_TEST_KEEP_MACROS)
|
JSON_TEST_KEEP_MACROS
|
||||||
|
JSON_TEST_USING_MULTIPLE_HEADERS=$<BOOL:${JSON_MultipleHeaders}>)
|
||||||
target_compile_features(test_main PRIVATE cxx_std_11)
|
target_compile_features(test_main PRIVATE cxx_std_11)
|
||||||
target_compile_options(test_main PUBLIC
|
target_compile_options(test_main PUBLIC
|
||||||
$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>
|
$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// build test with C++14
|
||||||
|
// JSON_HAS_CPP_14
|
||||||
|
|
||||||
TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_json)
|
TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_json)
|
||||||
{
|
{
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
@ -1488,3 +1491,304 @@ TEST_CASE_TEMPLATE("element access 2 (throwing tests)", Json, nlohmann::json, nl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// TODO(falbrechtskirchinger) merge with the other test case; clean up
|
||||||
|
TEST_CASE_TEMPLATE("element access 2 (additional value() tests)", Json, nlohmann::json, nlohmann::ordered_json)
|
||||||
|
{
|
||||||
|
using string_t = typename Json::string_t;
|
||||||
|
using number_integer_t = typename Json::number_integer_t;
|
||||||
|
|
||||||
|
// test assumes string_t and object_t::key_type are the same
|
||||||
|
REQUIRE(std::is_same<string_t, typename Json::object_t::key_type>::value);
|
||||||
|
|
||||||
|
Json j
|
||||||
|
{
|
||||||
|
{"foo", "bar"},
|
||||||
|
{"baz", 42}
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* cpstr = "default";
|
||||||
|
const char castr[] = "default"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
|
||||||
|
string_t str = "default";
|
||||||
|
|
||||||
|
number_integer_t integer = 69;
|
||||||
|
std::size_t size = 69;
|
||||||
|
|
||||||
|
SECTION("deduced ValueType")
|
||||||
|
{
|
||||||
|
SECTION("literal key")
|
||||||
|
{
|
||||||
|
CHECK(j.value("foo", "default") == "bar");
|
||||||
|
CHECK(j.value("foo", cpstr) == "bar");
|
||||||
|
CHECK(j.value("foo", castr) == "bar");
|
||||||
|
CHECK(j.value("foo", str) == "bar");
|
||||||
|
// this test is in fact different than the one below,
|
||||||
|
// because of 0 considering const char * overloads
|
||||||
|
// where as any other number does not
|
||||||
|
CHECK(j.value("baz", 0) == 42);
|
||||||
|
CHECK(j.value("baz", 47) == 42);
|
||||||
|
CHECK(j.value("baz", integer) == 42);
|
||||||
|
CHECK(j.value("baz", size) == 42);
|
||||||
|
|
||||||
|
CHECK(j.value("bar", "default") == "default");
|
||||||
|
CHECK(j.value("bar", 0) == 0);
|
||||||
|
CHECK(j.value("bar", 47) == 47);
|
||||||
|
CHECK(j.value("bar", integer) == integer);
|
||||||
|
CHECK(j.value("bar", size) == size);
|
||||||
|
|
||||||
|
CHECK_THROWS_WITH_AS(Json().value("foo", "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(Json().value("foo", str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("const char * key")
|
||||||
|
{
|
||||||
|
const char* key = "foo";
|
||||||
|
const char* key2 = "baz";
|
||||||
|
const char* key_notfound = "bar";
|
||||||
|
|
||||||
|
CHECK(j.value(key, "default") == "bar");
|
||||||
|
CHECK(j.value(key, cpstr) == "bar");
|
||||||
|
CHECK(j.value(key, castr) == "bar");
|
||||||
|
CHECK(j.value(key, str) == "bar");
|
||||||
|
CHECK(j.value(key2, 0) == 42);
|
||||||
|
CHECK(j.value(key2, 47) == 42);
|
||||||
|
CHECK(j.value(key2, integer) == 42);
|
||||||
|
CHECK(j.value(key2, size) == 42);
|
||||||
|
|
||||||
|
CHECK(j.value(key_notfound, "default") == "default");
|
||||||
|
CHECK(j.value(key_notfound, 0) == 0);
|
||||||
|
CHECK(j.value(key_notfound, 47) == 47);
|
||||||
|
CHECK(j.value(key_notfound, integer) == integer);
|
||||||
|
CHECK(j.value(key_notfound, size) == size);
|
||||||
|
|
||||||
|
CHECK_THROWS_WITH_AS(Json().value(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(Json().value(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("const char(&)[] key")
|
||||||
|
{
|
||||||
|
const char key[] = "foo"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
|
||||||
|
const char key2[] = "baz"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
|
||||||
|
const char key_notfound[] = "bar"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
|
||||||
|
|
||||||
|
CHECK(j.value(key, "default") == "bar");
|
||||||
|
CHECK(j.value(key, cpstr) == "bar");
|
||||||
|
CHECK(j.value(key, castr) == "bar");
|
||||||
|
CHECK(j.value(key, str) == "bar");
|
||||||
|
CHECK(j.value(key2, 0) == 42);
|
||||||
|
CHECK(j.value(key2, 47) == 42);
|
||||||
|
CHECK(j.value(key2, integer) == 42);
|
||||||
|
CHECK(j.value(key2, size) == 42);
|
||||||
|
|
||||||
|
CHECK(j.value(key_notfound, "default") == "default");
|
||||||
|
CHECK(j.value(key_notfound, 0) == 0);
|
||||||
|
CHECK(j.value(key_notfound, 47) == 47);
|
||||||
|
CHECK(j.value(key_notfound, integer) == integer);
|
||||||
|
CHECK(j.value(key_notfound, size) == size);
|
||||||
|
|
||||||
|
CHECK_THROWS_WITH_AS(Json().value(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(Json().value(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("string_t/object_t::key_type key")
|
||||||
|
{
|
||||||
|
string_t key = "foo";
|
||||||
|
string_t key2 = "baz";
|
||||||
|
string_t key_notfound = "bar";
|
||||||
|
|
||||||
|
CHECK(j.value(key, "default") == "bar");
|
||||||
|
CHECK(j.value(key, cpstr) == "bar");
|
||||||
|
CHECK(j.value(key, castr) == "bar");
|
||||||
|
CHECK(j.value(key, str) == "bar");
|
||||||
|
CHECK(j.value(key2, 0) == 42);
|
||||||
|
CHECK(j.value(key2, 47) == 42);
|
||||||
|
CHECK(j.value(key2, integer) == 42);
|
||||||
|
CHECK(j.value(key2, size) == 42);
|
||||||
|
|
||||||
|
CHECK(j.value(key_notfound, "default") == "default");
|
||||||
|
CHECK(j.value(key_notfound, 0) == 0);
|
||||||
|
CHECK(j.value(key_notfound, 47) == 47);
|
||||||
|
CHECK(j.value(key_notfound, integer) == integer);
|
||||||
|
CHECK(j.value(key_notfound, size) == size);
|
||||||
|
|
||||||
|
CHECK_THROWS_WITH_AS(Json().value(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(Json().value(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef JSON_HAS_CPP_17
|
||||||
|
SECTION("std::string_view key")
|
||||||
|
{
|
||||||
|
std::string_view key = "foo";
|
||||||
|
std::string_view key2 = "baz";
|
||||||
|
std::string_view key_notfound = "bar";
|
||||||
|
|
||||||
|
CHECK(j.value(key, "default") == "bar");
|
||||||
|
CHECK(j.value(key, cpstr) == "bar");
|
||||||
|
CHECK(j.value(key, castr) == "bar");
|
||||||
|
CHECK(j.value(key, str) == "bar");
|
||||||
|
CHECK(j.value(key2, 0) == 42);
|
||||||
|
CHECK(j.value(key2, 47) == 42);
|
||||||
|
CHECK(j.value(key2, integer) == 42);
|
||||||
|
CHECK(j.value(key2, size) == 42);
|
||||||
|
|
||||||
|
CHECK(j.value(key_notfound, "default") == "default");
|
||||||
|
CHECK(j.value(key_notfound, 0) == 0);
|
||||||
|
CHECK(j.value(key_notfound, 47) == 47);
|
||||||
|
CHECK(j.value(key_notfound, integer) == integer);
|
||||||
|
CHECK(j.value(key_notfound, size) == size);
|
||||||
|
|
||||||
|
CHECK_THROWS_WITH_AS(Json().value(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(Json().value(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("explicit ValueType")
|
||||||
|
{
|
||||||
|
SECTION("literal key")
|
||||||
|
{
|
||||||
|
CHECK(j.template value<string_t>("foo", "default") == "bar");
|
||||||
|
CHECK(j.template value<string_t>("foo", cpstr) == "bar");
|
||||||
|
CHECK(j.template value<string_t>("foo", castr) == "bar");
|
||||||
|
CHECK(j.template value<string_t>("foo", str) == "bar");
|
||||||
|
CHECK(j.template value<number_integer_t>("baz", 0) == 42);
|
||||||
|
CHECK(j.template value<number_integer_t>("baz", 47) == 42);
|
||||||
|
CHECK(j.template value<number_integer_t>("baz", integer) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>("baz", 0) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>("baz", 47) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>("baz", size) == 42);
|
||||||
|
|
||||||
|
CHECK(j.template value<string_t>("bar", "default") == "default");
|
||||||
|
CHECK(j.template value<number_integer_t>("bar", 0) == 0);
|
||||||
|
CHECK(j.template value<number_integer_t>("bar", 47) == 47);
|
||||||
|
CHECK(j.template value<number_integer_t>("bar", integer) == integer);
|
||||||
|
CHECK(j.template value<std::size_t>("bar", 0) == 0);
|
||||||
|
CHECK(j.template value<std::size_t>("bar", 47) == 47);
|
||||||
|
CHECK(j.template value<std::size_t>("bar", size) == size);
|
||||||
|
|
||||||
|
CHECK_THROWS_WITH_AS(Json().template value<string_t>("foo", "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(Json().template value<string_t>("foo", str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("const char * key")
|
||||||
|
{
|
||||||
|
const char* key = "foo";
|
||||||
|
const char* key2 = "baz";
|
||||||
|
const char* key_notfound = "bar";
|
||||||
|
|
||||||
|
CHECK(j.template value<string_t>(key, "default") == "bar");
|
||||||
|
CHECK(j.template value<string_t>(key, cpstr) == "bar");
|
||||||
|
CHECK(j.template value<string_t>(key, castr) == "bar");
|
||||||
|
CHECK(j.template value<string_t>(key, str) == "bar");
|
||||||
|
CHECK(j.template value<number_integer_t>(key2, 0) == 42);
|
||||||
|
CHECK(j.template value<number_integer_t>(key2, 47) == 42);
|
||||||
|
CHECK(j.template value<number_integer_t>(key2, integer) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>(key2, 0) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>(key2, 47) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>(key2, size) == 42);
|
||||||
|
|
||||||
|
CHECK(j.template value<string_t>(key_notfound, "default") == "default");
|
||||||
|
CHECK(j.template value<number_integer_t>(key_notfound, 0) == 0);
|
||||||
|
CHECK(j.template value<number_integer_t>(key_notfound, 47) == 47);
|
||||||
|
CHECK(j.template value<number_integer_t>(key_notfound, integer) == integer);
|
||||||
|
CHECK(j.template value<std::size_t>(key_notfound, 0) == 0);
|
||||||
|
CHECK(j.template value<std::size_t>(key_notfound, 47) == 47);
|
||||||
|
CHECK(j.template value<std::size_t>(key_notfound, size) == size);
|
||||||
|
|
||||||
|
CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("const char(&)[] key")
|
||||||
|
{
|
||||||
|
const char key[] = "foo"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
|
||||||
|
const char key2[] = "baz"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
|
||||||
|
const char key_notfound[] = "bar"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
|
||||||
|
|
||||||
|
CHECK(j.template value<string_t>(key, "default") == "bar");
|
||||||
|
CHECK(j.template value<string_t>(key, cpstr) == "bar");
|
||||||
|
CHECK(j.template value<string_t>(key, castr) == "bar");
|
||||||
|
CHECK(j.template value<string_t>(key, str) == "bar");
|
||||||
|
CHECK(j.template value<number_integer_t>(key2, 0) == 42);
|
||||||
|
CHECK(j.template value<number_integer_t>(key2, 47) == 42);
|
||||||
|
CHECK(j.template value<number_integer_t>(key2, integer) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>(key2, 0) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>(key2, 47) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>(key2, size) == 42);
|
||||||
|
|
||||||
|
CHECK(j.template value<string_t>(key_notfound, "default") == "default");
|
||||||
|
CHECK(j.template value<number_integer_t>(key_notfound, 0) == 0);
|
||||||
|
CHECK(j.template value<number_integer_t>(key_notfound, 47) == 47);
|
||||||
|
CHECK(j.template value<number_integer_t>(key_notfound, integer) == integer);
|
||||||
|
CHECK(j.template value<std::size_t>(key_notfound, 0) == 0);
|
||||||
|
CHECK(j.template value<std::size_t>(key_notfound, 47) == 47);
|
||||||
|
CHECK(j.template value<std::size_t>(key_notfound, size) == size);
|
||||||
|
|
||||||
|
CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("string_t/object_t::key_type key")
|
||||||
|
{
|
||||||
|
string_t key = "foo";
|
||||||
|
string_t key2 = "baz";
|
||||||
|
string_t key_notfound = "bar";
|
||||||
|
|
||||||
|
CHECK(j.template value<string_t>(key, "default") == "bar");
|
||||||
|
CHECK(j.template value<string_t>(key, cpstr) == "bar");
|
||||||
|
CHECK(j.template value<string_t>(key, castr) == "bar");
|
||||||
|
CHECK(j.template value<string_t>(key, str) == "bar");
|
||||||
|
CHECK(j.template value<number_integer_t>(key2, 0) == 42);
|
||||||
|
CHECK(j.template value<number_integer_t>(key2, 47) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>(key2, 0) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>(key2, 47) == 42);
|
||||||
|
|
||||||
|
CHECK(j.template value<string_t>(key_notfound, "default") == "default");
|
||||||
|
CHECK(j.template value<number_integer_t>(key_notfound, 0) == 0);
|
||||||
|
CHECK(j.template value<number_integer_t>(key_notfound, 47) == 47);
|
||||||
|
CHECK(j.template value<std::size_t>(key_notfound, 0) == 0);
|
||||||
|
CHECK(j.template value<std::size_t>(key_notfound, 47) == 47);
|
||||||
|
|
||||||
|
CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef JSON_HAS_CPP_17
|
||||||
|
SECTION("std::string_view key")
|
||||||
|
{
|
||||||
|
std::string_view key = "foo";
|
||||||
|
std::string_view key2 = "baz";
|
||||||
|
std::string_view key_notfound = "bar";
|
||||||
|
|
||||||
|
CHECK(j.template value<string_t>(key, "default") == "bar");
|
||||||
|
CHECK(j.template value<string_t>(key, cpstr) == "bar");
|
||||||
|
CHECK(j.template value<string_t>(key, castr) == "bar");
|
||||||
|
CHECK(j.template value<string_t>(key, str) == "bar");
|
||||||
|
CHECK(j.template value<number_integer_t>(key2, 0) == 42);
|
||||||
|
CHECK(j.template value<number_integer_t>(key2, 47) == 42);
|
||||||
|
CHECK(j.template value<number_integer_t>(key2, integer) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>(key2, 0) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>(key2, 47) == 42);
|
||||||
|
CHECK(j.template value<std::size_t>(key2, size) == 42);
|
||||||
|
|
||||||
|
CHECK(j.template value<string_t>(key_notfound, "default") == "default");
|
||||||
|
CHECK(j.template value<number_integer_t>(key_notfound, 0) == 0);
|
||||||
|
CHECK(j.template value<number_integer_t>(key_notfound, 47) == 47);
|
||||||
|
CHECK(j.template value<number_integer_t>(key_notfound, integer) == integer);
|
||||||
|
CHECK(j.template value<std::size_t>(key_notfound, 0) == 0);
|
||||||
|
CHECK(j.template value<std::size_t>(key_notfound, 47) == 47);
|
||||||
|
CHECK(j.template value<std::size_t>(key_notfound, size) == size);
|
||||||
|
|
||||||
|
CHECK(j.template value<std::string_view>(key, "default") == "bar");
|
||||||
|
CHECK(j.template value<std::string_view>(key, cpstr) == "bar");
|
||||||
|
CHECK(j.template value<std::string_view>(key, castr) == "bar");
|
||||||
|
CHECK(j.template value<std::string_view>(key, str) == "bar");
|
||||||
|
|
||||||
|
CHECK(j.template value<std::string_view>(key_notfound, "default") == "default");
|
||||||
|
|
||||||
|
CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, "default"), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(Json().template value<string_t>(key, str), "[json.exception.type_error.306] cannot use value() with null", typename Json::type_error&);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
56
tests/src/unit-type_traits.cpp
Normal file
56
tests/src/unit-type_traits.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// __ _____ _____ _____
|
||||||
|
// __| | __| | | | JSON for Modern C++ (supporting code)
|
||||||
|
// | | |__ | | | | | | version 3.11.1
|
||||||
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#include "doctest_compatibility.h"
|
||||||
|
|
||||||
|
#if JSON_TEST_USING_MULTIPLE_HEADERS
|
||||||
|
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
|
#else
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TEST_CASE("type traits")
|
||||||
|
{
|
||||||
|
SECTION("is_c_string")
|
||||||
|
{
|
||||||
|
using nlohmann::detail::is_c_string;
|
||||||
|
using nlohmann::detail::is_c_string_uncvref;
|
||||||
|
|
||||||
|
SECTION("char *")
|
||||||
|
{
|
||||||
|
CHECK(is_c_string<char*>::value);
|
||||||
|
CHECK(is_c_string<const char*>::value);
|
||||||
|
CHECK(is_c_string<char* const>::value);
|
||||||
|
CHECK(is_c_string<const char* const>::value);
|
||||||
|
|
||||||
|
CHECK_FALSE(is_c_string<char*&>::value);
|
||||||
|
CHECK_FALSE(is_c_string<const char*&>::value);
|
||||||
|
CHECK_FALSE(is_c_string<char* const&>::value);
|
||||||
|
CHECK_FALSE(is_c_string<const char* const&>::value);
|
||||||
|
|
||||||
|
CHECK(is_c_string_uncvref<char*&>::value);
|
||||||
|
CHECK(is_c_string_uncvref<const char*&>::value);
|
||||||
|
CHECK(is_c_string_uncvref<char* const&>::value);
|
||||||
|
CHECK(is_c_string_uncvref<const char* const&>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("char[]")
|
||||||
|
{
|
||||||
|
// NOLINTBEGIN(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
|
||||||
|
CHECK(is_c_string<char[]>::value);
|
||||||
|
CHECK(is_c_string<const char[]>::value);
|
||||||
|
|
||||||
|
CHECK_FALSE(is_c_string<char(&)[]>::value);
|
||||||
|
CHECK_FALSE(is_c_string<const char(&)[]>::value);
|
||||||
|
|
||||||
|
CHECK(is_c_string_uncvref<char(&)[]>::value);
|
||||||
|
CHECK(is_c_string_uncvref<const char(&)[]>::value);
|
||||||
|
// NOLINTEND(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user