Skip to content

Commit

Permalink
Add backwards compatibility with json_pointer<basic_json>
Browse files Browse the repository at this point in the history
  • Loading branch information
falbrechtskirchinger committed Apr 4, 2022
1 parent c96111f commit 081bce9
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 4 deletions.
33 changes: 32 additions & 1 deletion include/nlohmann/detail/json_pointer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,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/
Expand Down Expand Up @@ -799,6 +815,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
Expand Down
5 changes: 5 additions & 0 deletions include/nlohmann/detail/meta/type_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,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 //
//////////////////////
Expand Down
53 changes: 52 additions & 1 deletion include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2210,6 +2210,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(3.10.6)
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*
Expand All @@ -2219,6 +2227,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return value(ptr, string_t(default_value));
}

template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED(3.10.6)
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()
Expand Down Expand Up @@ -2481,7 +2497,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();
Expand All @@ -2494,6 +2510,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.contains(this);
}

template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED(3.10.6)
bool contains(const typename ::nlohmann::json_pointer<BasicJsonType> ptr) const
{
return ptr.contains(this);
}

/// @}


Expand Down Expand Up @@ -4182,27 +4205,55 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_unchecked(this);
}

template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED(3.10.6)
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
{
return ptr.get_unchecked(this);
}

template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED(3.10.6)
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)
{
return ptr.get_checked(this);
}

template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED(3.10.6)
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
{
return ptr.get_checked(this);
}

template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED(3.10.6)
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
Expand Down
91 changes: 89 additions & 2 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3172,6 +3172,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 //
//////////////////////
Expand Down Expand Up @@ -12470,8 +12475,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/
Expand Down Expand Up @@ -13243,6 +13264,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

Expand Down Expand Up @@ -19607,6 +19643,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(3.10.6)
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*
Expand All @@ -19616,6 +19660,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return value(ptr, string_t(default_value));
}

template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED(3.10.6)
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()
Expand Down Expand Up @@ -19878,7 +19930,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();
Expand All @@ -19891,6 +19943,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.contains(this);
}

template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED(3.10.6)
bool contains(const typename ::nlohmann::json_pointer<BasicJsonType> ptr) const
{
return ptr.contains(this);
}

/// @}


Expand Down Expand Up @@ -21579,27 +21638,55 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_unchecked(this);
}

template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED(3.10.6)
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
{
return ptr.get_unchecked(this);
}

template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED(3.10.6)
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)
{
return ptr.get_checked(this);
}

template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED(3.10.6)
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
{
return ptr.get_checked(this);
}

template<typename BasicJsonType>
JSON_HEDLEY_DEPRECATED(3.10.6)
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
Expand Down
31 changes: 31 additions & 0 deletions test/src/unit-json_pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -660,4 +660,35 @@ 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>;

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"));
}
}

0 comments on commit 081bce9

Please sign in to comment.