diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index 744ef43f2..a9b208dfd 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -28,8 +28,24 @@ class json_pointer NLOHMANN_BASIC_JSON_TPL_DECLARATION friend class basic_json; + template + friend class json_pointer; + + template + struct string_t_helper + { + using type = T; + }; + + NLOHMANN_BASIC_JSON_TPL_DECLARATION + struct string_t_helper + { + using type = StringType; + }; + public: - using string_t = RefStringType; + // for backwards compatibility accept BasicJsonType + using string_t = typename string_t_helper::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 convert() const& + { + json_pointer result; + result.reference_tokens = reference_tokens; + return result; + } + + json_pointer convert()&& + { + json_pointer result; + result.reference_tokens = std::move(reference_tokens); + return result; + } + /*! @brief compares two JSON pointers for equality diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp index a4d8b6156..376c00a09 100644 --- a/include/nlohmann/detail/meta/type_traits.hpp +++ b/include/nlohmann/detail/meta/type_traits.hpp @@ -54,6 +54,11 @@ struct is_basic_json_context : || std::is_same::value > {}; +template struct is_json_pointer : std::false_type {}; + +template +struct is_json_pointer> : std::true_type {}; + ////////////////////// // json_ref helpers // ////////////////////// diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 481b06cab..a5f299170 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -129,7 +129,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { private: template friend struct detail::external_constructor; - friend ::nlohmann::json_pointer; + + template + friend class ::nlohmann::json_pointer; + // can be restored when json_pointer backwards compatibility is removed + // friend ::nlohmann::json_pointer; template 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::value, int>::type = 0> + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + ValueType value(const ::nlohmann::json_pointer& 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 + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + JSON_HEDLEY_NON_NULL(3) + string_t value(const typename ::nlohmann::json_pointer& 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::type, json_pointer>::value, int >::type = 0 > + !detail::is_json_pointer::type>::value, int >::type = 0 > bool contains(KeyT && key) const { return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); @@ -2505,6 +2525,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return ptr.contains(this); } + template + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + bool contains(const typename ::nlohmann::json_pointer 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 + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + reference operator[](const ::nlohmann::json_pointer& 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 + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + const_reference operator[](const ::nlohmann::json_pointer& 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 + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + reference at(const ::nlohmann::json_pointer& 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 + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + const_reference at(const ::nlohmann::json_pointer& 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 diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 0df5c9435..56d02b7f0 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -3183,6 +3183,11 @@ struct is_basic_json_context : || std::is_same::value > {}; +template struct is_json_pointer : std::false_type {}; + +template +struct is_json_pointer> : std::true_type {}; + ////////////////////// // json_ref helpers // ////////////////////// @@ -12488,8 +12493,24 @@ class json_pointer NLOHMANN_BASIC_JSON_TPL_DECLARATION friend class basic_json; + template + friend class json_pointer; + + template + struct string_t_helper + { + using type = T; + }; + + NLOHMANN_BASIC_JSON_TPL_DECLARATION + struct string_t_helper + { + using type = StringType; + }; + public: - using string_t = RefStringType; + // for backwards compatibility accept BasicJsonType + using string_t = typename string_t_helper::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 convert() const& + { + json_pointer result; + result.reference_tokens = reference_tokens; + return result; + } + + json_pointer convert()&& + { + json_pointer 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 friend struct detail::external_constructor; - friend ::nlohmann::json_pointer; + + template + friend class ::nlohmann::json_pointer; + // can be restored when json_pointer backwards compatibility is removed + // friend ::nlohmann::json_pointer; template 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::value, int>::type = 0> + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + ValueType value(const ::nlohmann::json_pointer& 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 + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + JSON_HEDLEY_NON_NULL(3) + string_t value(const typename ::nlohmann::json_pointer& 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::type, json_pointer>::value, int >::type = 0 > + !detail::is_json_pointer::type>::value, int >::type = 0 > bool contains(KeyT && key) const { return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); @@ -19905,6 +19961,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return ptr.contains(this); } + template + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + bool contains(const typename ::nlohmann::json_pointer 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 + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + reference operator[](const ::nlohmann::json_pointer& 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 + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + const_reference operator[](const ::nlohmann::json_pointer& 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 + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + reference at(const ::nlohmann::json_pointer& 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 + JSON_HEDLEY_DEPRECATED_FOR(3.10.6, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) + const_reference at(const ::nlohmann::json_pointer& 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 diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp index 8853c7aa6..7b7380792 100644 --- a/test/src/unit-json_pointer.cpp +++ b/test/src/unit-json_pointer.cpp @@ -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; + using json_ptr_j = nlohmann::json_pointer; + using json_ptr_oj = nlohmann::json_pointer; + + CHECK(std::is_same::value); + CHECK(std::is_same::value); + CHECK(std::is_same::value); + CHECK(std::is_same::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")); + } }