Add backwards compatibility with json_pointer<basic_json>

This commit is contained in:
Florian Albrechtskirchinger 2022-04-04 12:03:01 +02:00
parent 6f319322ac
commit 38f251f158
5 changed files with 224 additions and 6 deletions

View File

@ -28,8 +28,24 @@ class json_pointer
NLOHMANN_BASIC_JSON_TPL_DECLARATION
friend class basic_json;
template<typename>
friend class json_pointer;
template<typename T>
struct string_t_helper
{
using type = T;
};
NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
{
using type = StringType;
};
public:
using string_t = RefStringType;
// for backwards compatibility accept BasicJsonType
using string_t = typename string_t_helper<RefStringType>::type;
/// @brief create JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
@ -794,6 +810,21 @@ class json_pointer
return result;
}
// can't use conversion operator because of ambiguity
json_pointer<string_t> convert() const&
{
json_pointer<string_t> result;
result.reference_tokens = reference_tokens;
return result;
}
json_pointer<string_t> convert()&&
{
json_pointer<string_t> result;
result.reference_tokens = std::move(reference_tokens);
return result;
}
/*!
@brief compares two JSON pointers for equality

View File

@ -54,6 +54,11 @@ struct is_basic_json_context :
|| std::is_same<BasicJsonContext, std::nullptr_t>::value >
{};
template<typename> struct is_json_pointer : std::false_type {};
template<typename RefStringType>
struct is_json_pointer<json_pointer<RefStringType>> : std::true_type {};
//////////////////////
// json_ref helpers //
//////////////////////

View File

@ -129,7 +129,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
private:
template<detail::value_t> friend struct detail::external_constructor;
friend ::nlohmann::json_pointer<StringType>;
template<typename>
friend class ::nlohmann::json_pointer;
// can be restored when json_pointer backwards compatibility is removed
// friend ::nlohmann::json_pointer<StringType>;
template<typename BasicJsonType, typename InputType>
friend class ::nlohmann::detail::parser;
@ -2221,6 +2225,14 @@ 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));
}
template<class ValueType, class BasicJsonType, typename std::enable_if<
detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, 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*
@ -2230,6 +2242,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return value(ptr, string_t(default_value));
}
template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, 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
{
return value(ptr.convert(), default_value);
}
/// @brief access the first element
/// @sa https://json.nlohmann.me/api/basic_json/front/
reference front()
@ -2492,7 +2512,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief check the existence of an element in a JSON object
/// @sa https://json.nlohmann.me/api/basic_json/contains/
template < typename KeyT, typename std::enable_if <
!std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int >::type = 0 >
!detail::is_json_pointer<typename std::decay<KeyT>::type>::value, int >::type = 0 >
bool contains(KeyT && key) const
{
return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
@ -2505,6 +2525,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.contains(this);
}
template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
bool contains(const typename ::nlohmann::json_pointer<BasicJsonType> ptr) const
{
return ptr.contains(this);
}
/// @}
@ -4193,6 +4220,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_unchecked(this);
}
template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
{
return ptr.get_unchecked(this);
}
/// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
const_reference operator[](const json_pointer& ptr) const
@ -4200,6 +4234,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_unchecked(this);
}
template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
{
return ptr.get_unchecked(this);
}
/// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/at/
reference at(const json_pointer& ptr)
@ -4207,6 +4248,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_checked(this);
}
template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
{
return ptr.get_checked(this);
}
/// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/at/
const_reference at(const json_pointer& ptr) const
@ -4214,6 +4262,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_checked(this);
}
template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
{
return ptr.get_checked(this);
}
/// @brief return flattened JSON value
/// @sa https://json.nlohmann.me/api/basic_json/flatten/
basic_json flatten() const

View File

@ -3183,6 +3183,11 @@ struct is_basic_json_context :
|| std::is_same<BasicJsonContext, std::nullptr_t>::value >
{};
template<typename> struct is_json_pointer : std::false_type {};
template<typename RefStringType>
struct is_json_pointer<json_pointer<RefStringType>> : std::true_type {};
//////////////////////
// json_ref helpers //
//////////////////////
@ -12488,8 +12493,24 @@ class json_pointer
NLOHMANN_BASIC_JSON_TPL_DECLARATION
friend class basic_json;
template<typename>
friend class json_pointer;
template<typename T>
struct string_t_helper
{
using type = T;
};
NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
{
using type = StringType;
};
public:
using string_t = RefStringType;
// for backwards compatibility accept BasicJsonType
using string_t = typename string_t_helper<RefStringType>::type;
/// @brief create JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
@ -13254,6 +13275,21 @@ class json_pointer
return result;
}
// can't use conversion operator because of ambiguity
json_pointer<string_t> convert() const&
{
json_pointer<string_t> result;
result.reference_tokens = reference_tokens;
return result;
}
json_pointer<string_t> convert()&&
{
json_pointer<string_t> result;
result.reference_tokens = std::move(reference_tokens);
return result;
}
/*!
@brief compares two JSON pointers for equality
@ -17529,7 +17565,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
private:
template<detail::value_t> friend struct detail::external_constructor;
friend ::nlohmann::json_pointer<StringType>;
template<typename>
friend class ::nlohmann::json_pointer;
// can be restored when json_pointer backwards compatibility is removed
// friend ::nlohmann::json_pointer<StringType>;
template<typename BasicJsonType, typename InputType>
friend class ::nlohmann::detail::parser;
@ -19621,6 +19661,14 @@ 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));
}
template<class ValueType, class BasicJsonType, typename std::enable_if<
detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, 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*
@ -19630,6 +19678,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return value(ptr, string_t(default_value));
}
template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, 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
{
return value(ptr.convert(), default_value);
}
/// @brief access the first element
/// @sa https://json.nlohmann.me/api/basic_json/front/
reference front()
@ -19892,7 +19948,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief check the existence of an element in a JSON object
/// @sa https://json.nlohmann.me/api/basic_json/contains/
template < typename KeyT, typename std::enable_if <
!std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int >::type = 0 >
!detail::is_json_pointer<typename std::decay<KeyT>::type>::value, int >::type = 0 >
bool contains(KeyT && key) const
{
return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
@ -19905,6 +19961,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.contains(this);
}
template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
bool contains(const typename ::nlohmann::json_pointer<BasicJsonType> ptr) const
{
return ptr.contains(this);
}
/// @}
@ -21593,6 +21656,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_unchecked(this);
}
template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
{
return ptr.get_unchecked(this);
}
/// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
const_reference operator[](const json_pointer& ptr) const
@ -21600,6 +21670,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_unchecked(this);
}
template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
{
return ptr.get_unchecked(this);
}
/// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/at/
reference at(const json_pointer& ptr)
@ -21607,6 +21684,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_checked(this);
}
template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
{
return ptr.get_checked(this);
}
/// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/at/
const_reference at(const json_pointer& ptr) const
@ -21614,6 +21698,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_checked(this);
}
template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
{
return ptr.get_checked(this);
}
/// @brief return flattened JSON value
/// @sa https://json.nlohmann.me/api/basic_json/flatten/
basic_json flatten() const

View File

@ -660,4 +660,40 @@ TEST_CASE("JSON pointers")
CHECK(j[ptr] == j["object"]["/"]);
CHECK(ptr.to_string() == "/object/~1");
}
SECTION("backwards compatibility and mixing")
{
json j = R"(
{
"foo": ["bar", "baz"]
}
)"_json;
using nlohmann::ordered_json;
using json_ptr_str = nlohmann::json_pointer<std::string>;
using json_ptr_j = nlohmann::json_pointer<json>;
using json_ptr_oj = nlohmann::json_pointer<ordered_json>;
CHECK(std::is_same<json_ptr_str::string_t, json::json_pointer::string_t>::value);
CHECK(std::is_same<json_ptr_str::string_t, ordered_json::json_pointer::string_t>::value);
CHECK(std::is_same<json_ptr_str::string_t, json_ptr_j::string_t>::value);
CHECK(std::is_same<json_ptr_str::string_t, json_ptr_oj::string_t>::value);
json_ptr_str ptr{"/foo/0"};
json_ptr_j ptr_j{"/foo/0"};
json_ptr_oj ptr_oj{"/foo/0"};
CHECK(j.contains(ptr));
CHECK(j.contains(ptr_j));
CHECK(j.contains(ptr_oj));
CHECK(j.at(ptr) == j.at(ptr_j));
CHECK(j.at(ptr) == j.at(ptr_oj));
CHECK(j[ptr] == j[ptr_j]);
CHECK(j[ptr] == j[ptr_oj]);
CHECK(j.value(ptr, "x") == j.value(ptr_j, "x"));
CHECK(j.value(ptr, "x") == j.value(ptr_oj, "x"));
}
}