json icon indicating copy to clipboard operation
json copied to clipboard

nlohman::ordered_json using deprecated operators on calls to .value and .at with join_pointers

Open jllansford opened this issue 10 months ago • 4 comments

Description

When using the .at or .value functions on a ordered_json object with a parameter type of json_pointer there is a deprecation warning due to the following functions being called:

template<typename RefStringTypeLhs, typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) 
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, const StringType& rhs)
{
    return lhs == json_pointer<RefStringTypeLhs>(rhs);
}

template<typename RefStringTypeRhs, typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) 
inline bool operator==(const StringType& lhs, const json_pointer<RefStringTypeRhs>& rhs)
{
    return json_pointer<RefStringTypeRhs>(lhs) == rhs;
}

Reproduction steps

The sample code should illustrate the problem.

Expected vs. actual results

.at and .value should ideally not depend on deprecated functions unless they themselves are deprecated.

Minimal code example

using json = nlohmann::ordered_json;
using json_pointer = json::json_pointer;

int main() {
    json j = {{"key", "value"}};
    json_pointer ptr("/key");

    auto value = j.at(ptr); //deprecation warning
    return 0;
}

Error messages

warning: 'operator==' is deprecated: Since 3.11.2; use operator==(json_pointer, json_pointer) [-Wdeprecated-declarations]

...

while substituting deduced template arguments into function template 'at' [with KeyType = json_pointer &, $1 = (no value)]

Compiler and operating system

gcc & clang

Library version

3.11.3

Validation

jllansford avatar Jan 23 '25 20:01 jllansford

Hi, I’m Artem from OSS Revival. We specialize in revitalizing and maintaining open-source projects for long-term stability. After some research, we found that this Issue is not valid. The equality operators described above are not used while at() function calling, and are correctly marked as deprecated. A warning arises due to the Clang-tidy checks the entire file code, not just what is really used. To make sure of this, it is enough to remove/comment these templates from the code, and execute the program. The result will be the same.

ghost avatar Feb 18 '25 06:02 ghost

hi @Artem-OSSRevival, this seems like the issue I've encountered as well https://github.com/nlohmann/json/discussions/4788. is this expected to be solved in some future releases of the library?

tpolonijo avatar May 19 '25 11:05 tpolonijo

I see the following warning with GCC for

#include <nlohmann/json.hpp>

using json = nlohmann::ordered_json;
using json_pointer = json::json_pointer;

int main() {
    json j = {{"key", "value"}};
    json_pointer ptr("/key");

    auto value = j.at(ptr); //deprecation warning
    return 0;
}
g++-12 -std=c++11 issue4621.cpp -I include 
In file included from include/nlohmann/detail/exceptions.hpp:25,
                 from include/nlohmann/detail/conversions/from_json.hpp:23,
                 from include/nlohmann/adl_serializer.hpp:14,
                 from include/nlohmann/json.hpp:34,
                 from issue4621.cpp:1:
include/nlohmann/detail/meta/type_traits.hpp: In instantiation of 'struct nlohmann::json_abi_v3_12_0::detail::is_comparable<std::equal_to<std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, nlohmann::json_abi_v3_12_0::json_pointer<std::__cxx11::basic_string<char> >&, void>':
include/nlohmann/detail/meta/type_traits.hpp:607:31:   required by substitution of 'template<class KeyType, typename std::enable_if<typename std::conditional<(typename std::conditional<(((nlohmann::json_abi_v3_12_0::detail::is_comparable<std::equal_to<std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, KeyType, void>::value && (!(true && std::is_same<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::__cxx11::basic_string<char> >::value))) && ((! true) || std::integral_constant<bool, false>::value)) && (! nlohmann::json_abi_v3_12_0::detail::is_specialization_of<nlohmann::json_abi_v3_12_0::json_pointer, typename std::remove_cv<typename std::remove_reference<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type>::type>::type>::value)), std::integral_constant<bool, true>, std::integral_constant<bool, false> >::type::value && (! nlohmann::json_abi_v3_12_0::detail::is_json_iterator_of<nlohmann::json_abi_v3_12_0::basic_json<nlohmann::json_abi_v3_12_0::ordered_map>, typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type>::value)), std::integral_constant<bool, true>, std::integral_constant<bool, false> >::type::value, int>::type <anonymous> > const nlohmann::json_abi_v3_12_0::basic_json<nlohmann::json_abi_v3_12_0::ordered_map>::value_type& nlohmann::json_abi_v3_12_0::basic_json<nlohmann::json_abi_v3_12_0::ordered_map>::at(KeyType&&) const [with KeyType = nlohmann::json_abi_v3_12_0::json_pointer<std::__cxx11::basic_string<char> >&; typename std::enable_if<typename std::conditional<(typename std::conditional<(((nlohmann::json_abi_v3_12_0::detail::is_comparable<std::equal_to<std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char>, KeyType, void>::value && (!(true && std::is_same<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::__cxx11::basic_string<char> >::value))) && ((! true) || std::integral_constant<bool, false>::value)) && (! nlohmann::json_abi_v3_12_0::detail::is_specialization_of<nlohmann::json_abi_v3_12_0::json_pointer, typename std::remove_cv<typename std::remove_reference<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type>::type>::type>::value)), std::integral_constant<bool, true>, std::integral_constant<bool, false> >::type::value && (! nlohmann::json_abi_v3_12_0::detail::is_json_iterator_of<nlohmann::json_abi_v3_12_0::basic_json<nlohmann::json_abi_v3_12_0::ordered_map>, typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type>::value)), std::integral_constant<bool, true>, std::integral_constant<bool, false> >::type::value, int>::type <anonymous> = <missing>]'
issue4621.cpp:10:22:   required from here
include/nlohmann/detail/meta/type_traits.hpp:594:33: warning: 'nlohmann::json_abi_v3_12_0::json_pointer<RefStringType>::operator string_t() const [with RefStringType = std::__cxx11::basic_string<char>; string_t = std::__cxx11::basic_string<char>]' is deprecated: Since 3.11.0; use to_string() [-Wdeprecated-declarations]
  594 | decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
      |          ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from include/nlohmann/json.hpp:50:
include/nlohmann/detail/json_pointer.hpp:81:5: note: declared here
   81 |     operator string_t() const
      |     ^~~~~~~~
include/nlohmann/detail/meta/type_traits.hpp:595:33: warning: 'nlohmann::json_abi_v3_12_0::json_pointer<RefStringType>::operator string_t() const [with RefStringType = std::__cxx11::basic_string<char>; string_t = std::__cxx11::basic_string<char>]' is deprecated: Since 3.11.0; use to_string() [-Wdeprecated-declarations]
  595 | decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
      |          ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/nlohmann/detail/json_pointer.hpp:81:5: note: declared here
   81 |     operator string_t() const
      |     ^~~~~~~~
include/nlohmann/detail/meta/type_traits.hpp:594:33: warning: 'nlohmann::json_abi_v3_12_0::json_pointer<RefStringType>::operator string_t() const [with RefStringType = std::__cxx11::basic_string<char>; string_t = std::__cxx11::basic_string<char>]' is deprecated: Since 3.11.0; use to_string() [-Wdeprecated-declarations]
  594 | decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
      |          ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/nlohmann/detail/json_pointer.hpp:81:5: note: declared here
   81 |     operator string_t() const
      |     ^~~~~~~~
include/nlohmann/detail/meta/type_traits.hpp:595:33: warning: 'nlohmann::json_abi_v3_12_0::json_pointer<RefStringType>::operator string_t() const [with RefStringType = std::__cxx11::basic_string<char>; string_t = std::__cxx11::basic_string<char>]' is deprecated: Since 3.11.0; use to_string() [-Wdeprecated-declarations]
  595 | decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
      |          ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/nlohmann/detail/json_pointer.hpp:81:5: note: declared here
   81 |     operator string_t() const
      |     ^~~~~~~~

Some observations:

  1. Clang does not produce this warning.
  2. operator json_pointer::string_t() const is deprecated, but not called in the code. In fact, I can remove it from the library and the warning disappears.

So it seems GCC decides to use operator string_t() while checking detail::is_usable_as_key_type which checks detail::is_comparable which then comes to

template<typename Compare, typename A, typename B>
struct is_comparable<Compare, A, B, void_t<
decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
>> : std::true_type {};

which uses the deprecated operator json_pointer::string_t() const.

I will check.

nlohmann avatar May 21 '25 08:05 nlohmann

PTAL #4791

nlohmann avatar May 21 '25 12:05 nlohmann