mirror of
https://github.com/nlohmann/json.git
synced 2026-10-01 12:10:32 +00:00
Deduplicate the lookup/default/throw body of value()
The six non-deprecated value() overloads each held a full copy of the same body: the four key-based overloads looked up the key and either returned the found element converted to the requested type or the default value (throwing type_error.306 if this is not an object), and the two json_pointer overloads did the same via ptr.get_checked_or_null(), throwing type_error.306 unless is_structured(). Replace the duplicated bodies with two private helpers, value_member() and value_pointee(), that return a const basic_json* (null when not found) and do the type check/throw once each. Every value() overload now just picks between the found pointer's get<T>() and the default. Same signatures, template parameters, SFINAE conditions, exception id, message and this context on every overload. Overlaps #5689 (routes find() through lookup_key()) and #5705 (adds a deleted integral-key value() next to these overloads); whichever of this commit and those PRs lands second will need a small rebase. #5724 item 4 Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
+50
-86
@@ -2958,6 +2958,36 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
detail::is_c_string_uncvref<ValueType>::value,
|
||||
string_t, typename std::decay<ValueType>::type >;
|
||||
|
||||
/// @brief look up @a key for value(), the single place shared by all key-based overloads
|
||||
/// @throw type_error.306 if this is not an object
|
||||
/// @return a pointer to the found value, or `nullptr` if @a key was not found
|
||||
template<typename KeyType>
|
||||
const basic_json* value_member(KeyType&& key) const
|
||||
{
|
||||
// value only works for objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
}
|
||||
|
||||
const auto it = find(std::forward<KeyType>(key));
|
||||
return it != end() ? &*it : nullptr;
|
||||
}
|
||||
|
||||
/// @brief resolve @a ptr for value(), the single place shared by both json_pointer overloads
|
||||
/// @throw type_error.306 if this is not an array or object
|
||||
/// @return a pointer to the resolved value, or `nullptr` if @a ptr does not resolve
|
||||
const basic_json* value_pointee(const json_pointer& ptr) const
|
||||
{
|
||||
// value only works for arrays and objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_structured()))
|
||||
{
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
}
|
||||
|
||||
return ptr.get_checked_or_null(this);
|
||||
}
|
||||
|
||||
public:
|
||||
/// @brief access specified object element with default value
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
@@ -2967,20 +2997,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
&& !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()))
|
||||
{
|
||||
// If 'key' is found, return its value. Otherwise, return `default_value'.
|
||||
const auto it = find(key);
|
||||
if (it != end())
|
||||
{
|
||||
return it->template get<ValueType>();
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
// If 'key' is found, return its value. Otherwise, return `default_value'.
|
||||
const auto* found = value_member(key);
|
||||
return found != nullptr ? found->template get<ValueType>() : default_value;
|
||||
}
|
||||
|
||||
/// @brief access specified object element with default value
|
||||
@@ -2992,20 +3011,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
&& !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 its value. Otherwise, return `default_value'.
|
||||
const auto it = find(key);
|
||||
if (it != end())
|
||||
{
|
||||
return it->template get<ReturnType>();
|
||||
}
|
||||
|
||||
return std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
// If 'key' is found, return its value. Otherwise, return `default_value'.
|
||||
const auto* found = value_member(key);
|
||||
return found != nullptr ? found->template get<ReturnType>() : std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
/// @brief access specified object element with default value
|
||||
@@ -3018,20 +3026,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
&& !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()))
|
||||
{
|
||||
// If 'key' is found, return its value. Otherwise, return `default_value'.
|
||||
const auto it = find(std::forward<KeyType>(key));
|
||||
if (it != end())
|
||||
{
|
||||
return it->template get<ValueType>();
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
// If 'key' is found, return its value. Otherwise, return `default_value'.
|
||||
const auto* found = value_member(std::forward<KeyType>(key));
|
||||
return found != nullptr ? found->template get<ValueType>() : default_value;
|
||||
}
|
||||
|
||||
/// @brief access specified object element with default value
|
||||
@@ -3045,20 +3042,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
&& !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 its value. Otherwise, return `default_value'.
|
||||
const auto it = find(std::forward<KeyType>(key));
|
||||
if (it != end())
|
||||
{
|
||||
return it->template get<ReturnType>();
|
||||
}
|
||||
|
||||
return std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
// If 'key' is found, return its value. Otherwise, return `default_value'.
|
||||
const auto* found = value_member(std::forward<KeyType>(key));
|
||||
return found != nullptr ? found->template get<ReturnType>() : std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
/// @brief access specified object element via JSON Pointer with default value
|
||||
@@ -3068,21 +3054,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
&& !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 arrays and objects
|
||||
if (JSON_HEDLEY_LIKELY(is_structured()))
|
||||
{
|
||||
// If the pointer resolves to a value, return it. Otherwise, return
|
||||
// 'default_value'.
|
||||
const auto* res = ptr.get_checked_or_null(this);
|
||||
if (JSON_HEDLEY_LIKELY(res != nullptr))
|
||||
{
|
||||
return res->template get<ValueType>();
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
// If the pointer resolves to a value, return it. Otherwise, return
|
||||
// 'default_value'.
|
||||
const auto* found = value_pointee(ptr);
|
||||
return found != nullptr ? found->template get<ValueType>() : default_value;
|
||||
}
|
||||
|
||||
/// @brief access specified object element via JSON Pointer with default value
|
||||
@@ -3093,21 +3068,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
&& !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 arrays and objects
|
||||
if (JSON_HEDLEY_LIKELY(is_structured()))
|
||||
{
|
||||
// If the pointer resolves to a value, return it. Otherwise, return
|
||||
// 'default_value'.
|
||||
const auto* res = ptr.get_checked_or_null(this);
|
||||
if (JSON_HEDLEY_LIKELY(res != nullptr))
|
||||
{
|
||||
return res->template get<ReturnType>();
|
||||
}
|
||||
|
||||
return std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
// If the pointer resolves to a value, return it. Otherwise, return
|
||||
// 'default_value'.
|
||||
const auto* found = value_pointee(ptr);
|
||||
return found != nullptr ? found->template get<ReturnType>() : std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
template < class ValueType, class BasicJsonType, detail::enable_if_t <
|
||||
|
||||
@@ -29038,6 +29038,36 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
detail::is_c_string_uncvref<ValueType>::value,
|
||||
string_t, typename std::decay<ValueType>::type >;
|
||||
|
||||
/// @brief look up @a key for value(), the single place shared by all key-based overloads
|
||||
/// @throw type_error.306 if this is not an object
|
||||
/// @return a pointer to the found value, or `nullptr` if @a key was not found
|
||||
template<typename KeyType>
|
||||
const basic_json* value_member(KeyType&& key) const
|
||||
{
|
||||
// value only works for objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
}
|
||||
|
||||
const auto it = find(std::forward<KeyType>(key));
|
||||
return it != end() ? &*it : nullptr;
|
||||
}
|
||||
|
||||
/// @brief resolve @a ptr for value(), the single place shared by both json_pointer overloads
|
||||
/// @throw type_error.306 if this is not an array or object
|
||||
/// @return a pointer to the resolved value, or `nullptr` if @a ptr does not resolve
|
||||
const basic_json* value_pointee(const json_pointer& ptr) const
|
||||
{
|
||||
// value only works for arrays and objects
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_structured()))
|
||||
{
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
}
|
||||
|
||||
return ptr.get_checked_or_null(this);
|
||||
}
|
||||
|
||||
public:
|
||||
/// @brief access specified object element with default value
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/value/
|
||||
@@ -29047,20 +29077,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
&& !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()))
|
||||
{
|
||||
// If 'key' is found, return its value. Otherwise, return `default_value'.
|
||||
const auto it = find(key);
|
||||
if (it != end())
|
||||
{
|
||||
return it->template get<ValueType>();
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
// If 'key' is found, return its value. Otherwise, return `default_value'.
|
||||
const auto* found = value_member(key);
|
||||
return found != nullptr ? found->template get<ValueType>() : default_value;
|
||||
}
|
||||
|
||||
/// @brief access specified object element with default value
|
||||
@@ -29072,20 +29091,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
&& !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 its value. Otherwise, return `default_value'.
|
||||
const auto it = find(key);
|
||||
if (it != end())
|
||||
{
|
||||
return it->template get<ReturnType>();
|
||||
}
|
||||
|
||||
return std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
// If 'key' is found, return its value. Otherwise, return `default_value'.
|
||||
const auto* found = value_member(key);
|
||||
return found != nullptr ? found->template get<ReturnType>() : std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
/// @brief access specified object element with default value
|
||||
@@ -29098,20 +29106,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
&& !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()))
|
||||
{
|
||||
// If 'key' is found, return its value. Otherwise, return `default_value'.
|
||||
const auto it = find(std::forward<KeyType>(key));
|
||||
if (it != end())
|
||||
{
|
||||
return it->template get<ValueType>();
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
// If 'key' is found, return its value. Otherwise, return `default_value'.
|
||||
const auto* found = value_member(std::forward<KeyType>(key));
|
||||
return found != nullptr ? found->template get<ValueType>() : default_value;
|
||||
}
|
||||
|
||||
/// @brief access specified object element with default value
|
||||
@@ -29125,20 +29122,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
&& !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 its value. Otherwise, return `default_value'.
|
||||
const auto it = find(std::forward<KeyType>(key));
|
||||
if (it != end())
|
||||
{
|
||||
return it->template get<ReturnType>();
|
||||
}
|
||||
|
||||
return std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
// If 'key' is found, return its value. Otherwise, return `default_value'.
|
||||
const auto* found = value_member(std::forward<KeyType>(key));
|
||||
return found != nullptr ? found->template get<ReturnType>() : std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
/// @brief access specified object element via JSON Pointer with default value
|
||||
@@ -29148,21 +29134,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
&& !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 arrays and objects
|
||||
if (JSON_HEDLEY_LIKELY(is_structured()))
|
||||
{
|
||||
// If the pointer resolves to a value, return it. Otherwise, return
|
||||
// 'default_value'.
|
||||
const auto* res = ptr.get_checked_or_null(this);
|
||||
if (JSON_HEDLEY_LIKELY(res != nullptr))
|
||||
{
|
||||
return res->template get<ValueType>();
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
// If the pointer resolves to a value, return it. Otherwise, return
|
||||
// 'default_value'.
|
||||
const auto* found = value_pointee(ptr);
|
||||
return found != nullptr ? found->template get<ValueType>() : default_value;
|
||||
}
|
||||
|
||||
/// @brief access specified object element via JSON Pointer with default value
|
||||
@@ -29173,21 +29148,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
&& !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 arrays and objects
|
||||
if (JSON_HEDLEY_LIKELY(is_structured()))
|
||||
{
|
||||
// If the pointer resolves to a value, return it. Otherwise, return
|
||||
// 'default_value'.
|
||||
const auto* res = ptr.get_checked_or_null(this);
|
||||
if (JSON_HEDLEY_LIKELY(res != nullptr))
|
||||
{
|
||||
return res->template get<ReturnType>();
|
||||
}
|
||||
|
||||
return std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
|
||||
// If the pointer resolves to a value, return it. Otherwise, return
|
||||
// 'default_value'.
|
||||
const auto* found = value_pointee(ptr);
|
||||
return found != nullptr ? found->template get<ReturnType>() : std::forward<ValueType>(default_value);
|
||||
}
|
||||
|
||||
template < class ValueType, class BasicJsonType, detail::enable_if_t <
|
||||
|
||||
Reference in New Issue
Block a user