json icon indicating copy to clipboard operation
json copied to clipboard

The code used to build with 3.10.2 but fails now

Open me21 opened this issue 3 years ago • 6 comments

Description

I could convert nlohmann::json to a std::variant implicitly with version 3.10.2, but with the latest version, I can't.

With the latest version, the code doesn't build.

I don't know whether it is this way for a reason (I apologize if so), or a regression.

Reproduction steps

Try to build the given code.

Expected vs. actual results

The code used to build with v3.10.2, but it doesn't with the tip of develop branch.

Minimal code example

nlohmann::json test_json;
std::variant<size_t, std::string> val{test_json};

Error messages

error: no matching function for call to 'std::variant<unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::variant(<brace-enclosed initializer list>)'
[build]                          std::variant<size_t, std::string> val{test_json};
[build]                                                                         ^

Compiler and operating system

Windows 10, GCC 8.3.0 for ARM

Library version

a3e6e26dc83a726b292f5be0492fcc408663ce55

Validation

me21 avatar Oct 20 '22 08:10 me21

Oh, I found this: https://github.com/nlohmann/json/issues/958 It's not recommended to use implicit conversions anyway. I'm sorry.

me21 avatar Oct 20 '22 08:10 me21

I'm sorry again, on the second thought you were going to remove the support for implicit conversions from JSON in the next major version, so I thought you might still like to look at this.

me21 avatar Oct 20 '22 08:10 me21

Okay, I tried to change the code to

nlohmann::json test_json;
std::variant<size_t, std::string> val = test_json.get<std::variant<size_t, std::string>>();

and I still get the error:

error: no matching function for call to 'nlohmann::json_abi_v3_11_2::basic_json<>::get<std::variant<unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >()'
[build]                          std::variant<size_t, std::string> val = test_json.get<std::variant<size_t, std::string>>();
[build]                                                                                                                   ^

It seems the explicit conversion is also broken.

me21 avatar Oct 20 '22 08:10 me21

Based on the discussion in #1261, it was never assumed it should work and worked only by chance?.. I need to explicitly add variant support, correct?.. On another hand, that issue is about serialization, whereas I was interested in deserialization only. So I don't know if it should work, or the operation was never guaranteed.

me21 avatar Oct 31 '22 09:10 me21

The breaking commit was a87c1885cb784ea5b884ed6dd1c96e39b7b4ec64.

me21 avatar Oct 31 '22 10:10 me21

I have to take a closer look to be sure, but here are my initial thoughts: There's no built-in conversion for std::variant, meaning the compiler will look for any compatible conversion and won't find an unambiguous one.

I need to explicitly add variant support, correct?..

Yes, you need to provide your own to_json/from_json functions to implement the desired conversion behavior.

std::variant<size_t, std::string> val = test_json.get<std::variant<size_t, std::string>>();

This does not change the fact that there's no conversion available. The following lines should work instead:

std::variant<size_t, std::string> val = test_json.get<size_t>();
// or
std::variant<size_t, std::string> val = test_json.get<std::string>();

These calls can of course still fail at runtime, depending on the stored type.

falbrechtskirchinger avatar Nov 02 '22 15:11 falbrechtskirchinger

I understand, but the thing is that the code did build and run and work correctly with 3.10.2. It's like it queried the stored type under the hood and called the correct nlohmann::json::get specialization.

me21 avatar Apr 21 '23 10:04 me21

It seems that it was a bug before to have supported an example with std::variant.

nlohmann avatar Apr 22 '23 12:04 nlohmann

Did it break something? Because it is convenient, looks like a feature to me.

me21 avatar Apr 23 '23 20:04 me21