Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error occurred when converting nlohmann::json to std::any #3428

Closed
kotori2 opened this issue Apr 7, 2022 · 10 comments · Fixed by #3437
Closed

Error occurred when converting nlohmann::json to std::any #3428

kotori2 opened this issue Apr 7, 2022 · 10 comments · Fixed by #3437
Assignees
Labels
confirmed kind: bug platform: visual studio related to MSVC release item: 🐛 bug fix solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@kotori2
Copy link

kotori2 commented Apr 7, 2022

Description

I would like to store objects in a std::map<std::string, std::any>. But converting nlohmann::json to std::any throws error type must be string, but is

I can only reproduce this issue on Windows. macOS seems working fine.

Reproduction steps

Minimal test case:

#include <any>
#include <nlohmann/json.hpp>

int main() {
    nlohmann::json j;
    std::any &&a = j;
    return 0;
}

Expected vs. actual results

Expected: Runs without error
Actual: Exception: Exception 0xe06d7363 encountered at address 0x7ffa855c466c

Minimal code example

No response

Error messages

<unknown> 0x00007ffa855c466c
<unknown> 0x00007ffa6dcfb660
nlohmann::detail::from_json<nlohmann::basic_json<std::map,std::vector,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,bool,__int64,unsigned __int64,double,std::allocator,nlohmann::adl_serializer,std::vector<unsigned char,std::allocator<unsigned char> > >,std::any,0>(const nlohmann::basic_json<std::map,std::vector,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,bool,__int64,unsigned __int64,double,std::allocator,nlohmann::adl_serializer,std::vector<unsigned char,std::allocator<unsigned char> > > &,std::any &) from_json.hpp:118
nlohmann::detail::from_json_fn::operator()<nlohmann::basic_json<std::map,std::vector,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,bool,__int64,unsigned __int64,double,std::allocator,nlohmann::adl_serializer,std::vector<unsigned char,std::allocator<unsigned char> > >,std::any &>(const nlohmann::basic_json<std::map,std::vector,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,bool,__int64,unsigned __int64,double,std::allocator,nlohmann::adl_serializer,std::vector<unsigned char,std::allocator<unsigned char> > > &,std::any &) from_json.hpp:480
nlohmann::adl_serializer<std::any,void>::from_json<nlohmann::basic_json<std::map,std::vector,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,bool,__int64,unsigned __int64,double,std::allocator,nlohmann::adl_serializer,std::vector<unsigned char,std::allocator<unsigned char> > > const &,std::any>(const nlohmann::basic_json<std::map,std::vector,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,bool,__int64,unsigned __int64,double,std::allocator,nlohmann::adl_serializer,std::vector<unsigned char,std::allocator<unsigned char> > > &,std::any &) adl_serializer.hpp:25
nlohmann::basic_json<std::map,std::vector,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,bool,__int64,unsigned __int64,double,std::allocator,nlohmann::adl_serializer,std::vector<unsigned char,std::allocator<unsigned char> > >::get_impl<std::any,0>(priority_tag<0>) json.hpp:1613
nlohmann::basic_json<std::map,std::vector,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,bool,__int64,unsigned __int64,double,std::allocator,nlohmann::adl_serializer,std::vector<unsigned char,std::allocator<unsigned char> > >::get<std::any,std::any>() json.hpp:1756
nlohmann::basic_json<std::map,std::vector,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,bool,__int64,unsigned __int64,double,std::allocator,nlohmann::adl_serializer,std::vector<unsigned char,std::allocator<unsigned char> > >::operator<std::any,0> std::any() json.hpp:1900
main() main.cpp:7
invoke_main() 0x00007ff7cb0d12c9
__scrt_common_main_seh() 0x00007ff7cb0d116e
__scrt_common_main() 0x00007ff7cb0d102e
mainCRTStartup(void *) 0x00007ff7cb0d135e
<unknown> 0x00007ffa872d54e0
<unknown> 0x00007ffa87e8485b


### Compiler and operating system

MSVC 19.31.31104 on Windows 11 21H2

### Library version

current develop 15fa6a342af7b51cb51a22599026e01f1d81957b

### Validation

- [X] The bug also occurs if the latest version from the [`develop`](https://github.com/nlohmann/json/tree/develop) branch is used.
- [X] I can successfully [compile and run the unit tests](https://github.com/nlohmann/json#execute-unit-tests).
@falbrechtskirchinger
Copy link
Contributor

falbrechtskirchinger commented Apr 7, 2022

Seems to work just fine for me with trunk:
https://godbolt.org/z/jcv3Ejsnd

(GCC 11, Clang trunk, MSVC latest)

Edit: Oh wait. That's a runtime issue. My bad.

So, it's trying to assign the value as if std::any were a string type.

@nlohmann
Copy link
Owner

Can I close this issue then?

@kotori2
Copy link
Author

kotori2 commented Apr 11, 2022

But I didn't get it…… why std::any is a string type?

@nlohmann
Copy link
Owner

I cannot reproduce the runtime error.

@falbrechtskirchinger
Copy link
Contributor

falbrechtskirchinger commented Apr 11, 2022

I cannot reproduce the runtime error.

https://godbolt.org/z/T8fnsrKPz
This reproduces the issue.

from_json() for string types is called, hence the error.

Also, it only happens in the rvalue ref case and I haven't checked yet what type ends up being stored in the any when I remove the rvalue ref.

Edit: It is indeed a basic_json.

@nlohmann
Copy link
Owner

Thanks! So this only occurs on MSVC? Very strange. I would need to see the stack trace from the exception and the state of the basic_json value.

@falbrechtskirchinger
Copy link
Contributor

Thanks! So this only occurs on MSVC? Very strange. I would need to see the stack trace from the exception and the state of the basic_json value.

I just tried again with Clang (trunk) and it works just fine with the rvalue ref. a.type() indicates it does contain a basic_json as expected. I can try to step through it with a debugger when built with GCC/Clang to see how it differs from the MSVC stack trace above. But that would have to wait until tomorrow.

@kotori2
Copy link
Author

kotori2 commented Apr 11, 2022

Also, it only happens in the rvalue ref case

It seems on Apple Clang 13.1.6 and gcc 9.4.0 the copy constructor was called. The stack is also different from MSVC.

I would need to see the stack trace from the exception

I've posted the stack trace in the Error messages section.
image

@falbrechtskirchinger
Copy link
Contributor

falbrechtskirchinger commented Apr 12, 2022

I think this can be fixed by conditionally excluding std::any from being implicitly converted. Running it through CI right now.

Edit: I'm excluding it unconditionally, to suppress GCC compile failures with "-Werror=conversion".

falbrechtskirchinger added a commit to falbrechtskirchinger/json that referenced this issue Apr 12, 2022
Fixes nlohmann#3428 (MSVC) and silences compiler warning on GCC (-Wconversion).
@nlohmann nlohmann self-assigned this Apr 12, 2022
@nlohmann nlohmann added solution: proposed fix a fix for the issue has been proposed and waits for confirmation release item: 🐛 bug fix labels Apr 12, 2022
@nlohmann nlohmann added this to the Release 3.11.0 milestone Apr 12, 2022
nlohmann pushed a commit that referenced this issue Apr 12, 2022
* Exclude std::any from implicit conversion

Fixes #3428 (MSVC) and silences compiler warning on GCC (-Wconversion).

* Exclude std::any from implicit conversion
@kotori2
Copy link
Author

kotori2 commented Apr 12, 2022

@falbrechtskirchinger @nlohmann Thanks for your hard work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed kind: bug platform: visual studio related to MSVC release item: 🐛 bug fix solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants