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;
|
||||
|
||||
// (2)
|
||||
template<class KeyType, class ValueType>
|
||||
template<class ValueType, class KeyType>
|
||||
ValueType value(KeyType&& key,
|
||||
ValueType&& default_value) const;
|
||||
|
||||
@ -155,5 +155,5 @@ changes to any JSON value.
|
||||
## Version history
|
||||
|
||||
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.
|
||||
|
@ -684,5 +684,57 @@ inline constexpr bool value_in_range_of(T 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
|
||||
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));
|
||||
}
|
||||
|
||||
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
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
// this is the value(const typename object_t::key_type&) overload
|
||||
template < class KeyType, class ValueType, detail::enable_if_t <
|
||||
std::is_same<KeyType, typename object_t::key_type>::value
|
||||
template < class ValueType, detail::enable_if_t <
|
||||
!detail::is_transparent<object_comparator_t>::value
|
||||
&& detail::is_getable<basic_json_t, ValueType>::value
|
||||
&& !std::is_same<value_t, ValueType>::value, int > = 0 >
|
||||
typename std::decay<ValueType>::type value(const KeyType& key, ValueType && default_value) const
|
||||
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||
ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
|
||||
{
|
||||
// value only works for objects
|
||||
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);
|
||||
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);
|
||||
@ -2221,36 +2256,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @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*
|
||||
string_t value(const typename object_t::key_type& key, const char* default_value) const
|
||||
{
|
||||
return value(key, string_t(default_value));
|
||||
}
|
||||
|
||||
// these two functions, in conjunction with value(const KeyType &, ValueType &&),
|
||||
// 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
|
||||
template < class ValueType, class KeyType, 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, ValueType>::value
|
||||
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||
ValueType value(KeyType && key, const ValueType& default_value) const
|
||||
{
|
||||
// value only works for objects
|
||||
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));
|
||||
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);
|
||||
@ -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));
|
||||
}
|
||||
|
||||
/// @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
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
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
|
||||
{
|
||||
// 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));
|
||||
}
|
||||
|
||||
/// @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 <
|
||||
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)
|
||||
ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
|
||||
{
|
||||
return value(ptr.convert(), default_value);
|
||||
}
|
||||
|
||||
/// @brief access specified object element via JSON Pointer with default value
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
/// overload for a default value of type const char*
|
||||
JSON_HEDLEY_NON_NULL(3)
|
||||
string_t value(const json_pointer& ptr, const char* default_value) const
|
||||
{
|
||||
return value(ptr, string_t(default_value));
|
||||
}
|
||||
|
||||
template<typename BasicJsonType>
|
||||
template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
|
||||
detail::enable_if_t <
|
||||
detail::is_basic_json<BasicJsonType>::value
|
||||
&& detail::is_getable<basic_json_t, ReturnType>::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_NON_NULL(3)
|
||||
string_t value(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr, const char* default_value) const
|
||||
ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
|
||||
{
|
||||
return value(ptr.convert(), default_value);
|
||||
return value(ptr.convert(), std::forward<ValueType>(default_value));
|
||||
}
|
||||
|
||||
/// @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);
|
||||
}
|
||||
|
||||
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
|
||||
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));
|
||||
}
|
||||
|
||||
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
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
// this is the value(const typename object_t::key_type&) overload
|
||||
template < class KeyType, class ValueType, detail::enable_if_t <
|
||||
std::is_same<KeyType, typename object_t::key_type>::value
|
||||
template < class ValueType, detail::enable_if_t <
|
||||
!detail::is_transparent<object_comparator_t>::value
|
||||
&& detail::is_getable<basic_json_t, ValueType>::value
|
||||
&& !std::is_same<value_t, ValueType>::value, int > = 0 >
|
||||
typename std::decay<ValueType>::type value(const KeyType& key, ValueType && default_value) const
|
||||
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||
ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
|
||||
{
|
||||
// value only works for objects
|
||||
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);
|
||||
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);
|
||||
@ -21301,36 +21388,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @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*
|
||||
string_t value(const typename object_t::key_type& key, const char* default_value) const
|
||||
{
|
||||
return value(key, string_t(default_value));
|
||||
}
|
||||
|
||||
// these two functions, in conjunction with value(const KeyType &, ValueType &&),
|
||||
// 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
|
||||
template < class ValueType, class KeyType, 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, ValueType>::value
|
||||
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
|
||||
ValueType value(KeyType && key, const ValueType& default_value) const
|
||||
{
|
||||
// value only works for objects
|
||||
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));
|
||||
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);
|
||||
@ -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));
|
||||
}
|
||||
|
||||
/// @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
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
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
|
||||
{
|
||||
// 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));
|
||||
}
|
||||
|
||||
/// @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 <
|
||||
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)
|
||||
ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
|
||||
{
|
||||
return value(ptr.convert(), default_value);
|
||||
}
|
||||
|
||||
/// @brief access specified object element via JSON Pointer with default value
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
/// overload for a default value of type const char*
|
||||
JSON_HEDLEY_NON_NULL(3)
|
||||
string_t value(const json_pointer& ptr, const char* default_value) const
|
||||
{
|
||||
return value(ptr, string_t(default_value));
|
||||
}
|
||||
|
||||
template<typename BasicJsonType>
|
||||
template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
|
||||
detail::enable_if_t <
|
||||
detail::is_basic_json<BasicJsonType>::value
|
||||
&& detail::is_getable<basic_json_t, ReturnType>::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_NON_NULL(3)
|
||||
string_t value(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr, const char* default_value) const
|
||||
ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
|
||||
{
|
||||
return value(ptr.convert(), default_value);
|
||||
return value(ptr.convert(), std::forward<ValueType>(default_value));
|
||||
}
|
||||
|
||||
/// @brief access the first element
|
||||
|
@ -37,7 +37,8 @@ endif()
|
||||
add_library(test_main OBJECT src/unit.cpp)
|
||||
target_compile_definitions(test_main PUBLIC
|
||||
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_options(test_main PUBLIC
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>
|
||||
|
@ -14,6 +14,9 @@
|
||||
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
||||
#endif
|
||||
|
||||
// build test with C++14
|
||||
// JSON_HAS_CPP_14
|
||||
|
||||
TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_json)
|
||||
{
|
||||
SECTION("object")
|
||||
@ -1488,3 +1491,304 @@ TEST_CASE_TEMPLATE("element access 2 (throwing tests)", Json, nlohmann::json, nl
|
||||
}
|
||||
}
|
||||
#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