Json: I may not understand

Created on 15 Mar 2017  路  26Comments  路  Source: nlohmann/json

Hello, I'm new to C++.

I'm using Baylor's GNU licensed socket example to pull from omdbapi.com a JSON object with information about movies. This is for a non-academic class and it's a side project just to keep me busy while the class goes over the basics.

I have a std::string JSON and it has the value of:

{"Title":"Star Trek Beyond","Year":"2016","Rated":"PG-13","Released":"22 Jul 2016","Runtime":"122 min","Genre":"Action, Adventure, Sci-Fi","Director":"Justin Lin","Writer":"Simon Pegg, Doug Jung, Gene Roddenberry (based upon \"Star Trek\" created by)","Actors":"Chris Pine, Zachary Quinto, Karl Urban, Zoe Saldana","Plot":"The USS Enterprise crew explores the furthest reaches of uncharted space, where they encounter a new ruthless enemy who puts them and everything the Federation stands for to the test.","Language":"English","Country":"USA, Hong Kong, China","Awards":"Nominated for 1 Oscar. Another 1 win & 17 nominations.","Poster":"https://images-na.ssl-images-amazon.com/images/M/MV5BODgzN2E1YjctODg5Yi00YzYwLWJjZjAtNDg2MGE2Y2MyYjBmXkEyXkFqcGdeQXVyNjM1MTQ0NTQ@._V1_SX300.jpg","Metascore":"68","imdbRating":"7.1","imdbVotes":"154,036","imdbID":"tt2660888","Type":"movie","Response":"True"}

This is my code:

    string amazonData = getAmazonData("Star Trek Beyond");
string JSON = isolateJSON(&amazonData);
try {
    movieObject = json::parse(JSON);
}
catch (exception& e) {
    printf("%s\n", e.what());
}

VS has highlighted the json::parse and said "parse no instance of overloaded function". It appears to accept std::string so I'm not sure what the issue is.

Any help is appreciated.

question visual studio

Most helpful comment

printf("%d) %s.\n\tReleased in %d, received a rating of %.1f and is available on Amazon for $%.2f.\n\n", 1, movieObject["Title"], (int)movieObject["Year"], (double)movieObject["imdbRating"], 9.99);

movieObject["Year"] and movieObject["imdbRating"] are both strings: "Year":"2016" "imdbRating":"7.1"

string title = movieObject["Title"];
string year = movieObject["Year"];
string rating = movieObject["imdbRating"];
printf("%d) %s.\n\tReleased in %s, received a rating of %s and is available on Amazon for $%.2f.\n\n", 1, title.c_str(), year.c_str(), rating.c_str(), 9.99);

All 26 comments

Does it build even though intellisense is giving you an error? The intellisense compiler is different than the main compiler, so it may just be a problem with the intellisense compiler.

It compiles but it errors. This is the error stack:

Unhandled Exception: System.Runtime.InteropServices.SEHException: External component has thrown an exception.
at _CxxThrowException(Void* , _s__ThrowInfo* )
at nlohmann.detail.from_json,class std::allocator >,bool,__int64,unsigned __int64,double,class std::allocator,struct nlohmann::adl_serializer>,int,0>(basic_json\,std::allocator >\,bool\,__int64\,unsigned __int64\,double\,std::allocator\,nlohmann::adl_serializer>* j, Int32* val) in c:\users\dotlaptop\documents\visual studio 2015\projects\consoleapplication7\consoleapplication7\json.hpp:line 817
at nlohmann.detail.from_json_fn.call,class std::allocator >,bool,__int64,unsigned __int64,double,class std::allocator,struct nlohmann::adl_serializer>,int>(from_json_fn* , basic_json\,std::allocator >\,bool\,__int64\,unsigned __int64\,double\,std::allocator\,nlohmann::adl_serializer>* j, Int32* val, priority_tag<1> __unnamed002) in c:\users\dotlaptop\documents\visual studio 2015\projects\consoleapplication7\consoleapplication7\json.hpp:line 856
at nlohmann.detail.from_json_fn.operator(),class std::allocator >,bool,__int64,unsigned __int64,double,class std::allocator,struct nlohmann::adl_serializer>,int>(from_json_fn* , basic_json\,std::allocator >\,bool\,__int64\,unsigned __int64\,double\,std::allocator\,nlohmann::adl_serializer>* j, Int32* val) in c:\users\dotlaptop\documents\visual studio 2015\projects\consoleapplication7\consoleapplication7\json.hpp:line 871

Do you have an example of the JSON that's failing? Never mind, I see it.

This might be your problem:

"Writer":"Simon Pegg, Doug Jung, Gene Roddenberry (based upon "Star Trek" created by)",

Those quotes around Star Trek should be escaped.

The json I posted appears not to be the raw data, hang on and I'll grab the raw values.

This is the actual data in the JSON string. The value before I was grabbing from VS' visualizer but apparently it doesn't handle it correctly.

{"Title":"Star Trek Beyond","Year":"2016","Rated":"PG-13","Released":"22 Jul 2016","Runtime":"122 min","Genre":"Action, Adventure, Sci-Fi","Director":"Justin Lin","Writer":"Simon Pegg, Doug Jung, Gene Roddenberry (based upon \"Star Trek\" created by)","Actors":"Chris Pine, Zachary Quinto, Karl Urban, Zoe Saldana","Plot":"The USS Enterprise crew explores the furthest reaches of uncharted space, where they encounter a new ruthless enemy who puts them and everything the Federation stands for to the test.","Language":"English","Country":"USA, Hong Kong, China","Awards":"Nominated for 1 Oscar. Another 1 win & 17 nominations.","Poster":"https://images-na.ssl-images-amazon.com/images/M/MV5BODgzN2E1YjctODg5Yi00YzYwLWJjZjAtNDg2MGE2Y2MyYjBmXkEyXkFqcGdeQXVyNjM1MTQ0NTQ@._V1_SX300.jpg","Metascore":"68","imdbRating":"7.1","imdbVotes":"154,036","imdbID":"tt2660888","Type":"movie","Response":"True"}

This still has the same issue. It's invalid JSON.

Hmm, when I pasted it, it had the escape vals.
{"Title":"Star Trek Beyond","Year":"2016","Rated":"PG-13","Released":"22 Jul 2016","Runtime":"122 min","Genre":"Action, Adventure, Sci-Fi","Director":"Justin Lin","Writer":"Simon Pegg, Doug Jung, Gene Roddenberry (based upon \"Star Trek\" created by)","Actors":"Chris Pine, Zachary Quinto, Karl Urban, Zoe Saldana","Plot":"The USS Enterprise crew explores the furthest reaches of uncharted space, where they encounter a new ruthless enemy who puts them and everything the Federation stands for to the test.","Language":"English","Country":"USA, Hong Kong, China","Awards":"Nominated for 1 Oscar. Another 1 win & 17 nominations.","Poster":"https://images-na.ssl-images-amazon.com/images/M/MV5BODgzN2E1YjctODg5Yi00YzYwLWJjZjAtNDg2MGE2Y2MyYjBmXkEyXkFqcGdeQXVyNjM1MTQ0NTQ@._V1_SX300.jpg","Metascore":"68","imdbRating":"7.1","imdbVotes":"154,036","imdbID":"tt2660888","Type":"movie","Response":"True"}

Is that better?

Edit: It appears github was also messing with my escape characters.

Yes, much.

You can add three backticks around your example, like this.

```js
{"foo": "bar"}
```

This is then rendered as

{"foo": "bar"}

Do you know the release number or the commit hash of the version you're using, because it's not the head of master, the line numbers don't line up.

I can't be positive, but I think it's c7afb34e57fc7d343a6c6f3ddee859fe92a7cf92

Unhandled Exception: System.Runtime.InteropServices.SEHException: External component has thrown an exception.
at _CxxThrowException(Void* , _s__ThrowInfo* )
at from_json<basic_json<>,int,0>(basic_json<>* j, Int32* val) in json.hpp:line 817
at from_json_fn.call<basic_json<>,int>(from_json_fn* , basic_json<>* j, Int32* val, priority_tag<1> __unnamed002) in json.hpp:line 856
at from_json_fn.operator()<basic_json<>,int>(from_json_fn* , basic_json<>* j, Int32* val) in json.hpp:line 871

Reformatted, stripped namespaces, template params and paths, to make it easier to read.

Line 817 is:

            JSON_THROW(std::domain_error("type must be number, but is " + j.type_name()));

Do you have any more of the call stack? It seems weird to me that this error would come up in parse().

When I get back to the office tomorrow, I'll give the rest of the call stack.

This is the entire stack

Unhandled Exception: System.Runtime.InteropServices.SEHException: External component has thrown an exception.
   at _CxxThrowException(Void* , _s__ThrowInfo* )
   at nlohmann.detail.from_json<class nlohmann::basic_json<class std::map,class std::vector,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,bool,__int64,unsigned __int64,double,class std::allocator,struct nlohmann::adl_serializer>,int,0>(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>* j, Int32* val) in c:\users\dotlaptop\documents\visual studio 2015\projects\consoleapplication7\consoleapplication7\json.hpp:line 817
   at nlohmann.detail.from_json_fn.call<class nlohmann::basic_json<class std::map,class std::vector,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,bool,__int64,unsigned __int64,double,class std::allocator,struct nlohmann::adl_serializer>,int>(from_json_fn* , 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>* j, Int32* val, priority_tag<1> __unnamed002) in c:\users\dotlaptop\documents\visual studio 2015\projects\consoleapplication7\consoleapplication7\json.hpp:line 856
   at nlohmann.detail.from_json_fn.operator()<class nlohmann::basic_json<class std::map,class std::vector,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,bool,__int64,unsigned __int64,double,class std::allocator,struct nlohmann::adl_serializer>,int>(from_json_fn* , 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>* j, Int32* val) in c:\users\dotlaptop\documents\visual studio 2015\projects\consoleapplication7\consoleapplication7\json.hpp:line 871
   at nlohmann.adl_serializer<int,void>.from_json<class nlohmann::basic_json<class std::map,class std::vector,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,bool,__int64,unsigned __int64,double,class std::allocator,struct nlohmann::adl_serializer> const &,int>(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>* j, Int32* val) in c:\users\dotlaptop\documents\visual studio 2015\projects\consoleapplication7\consoleapplication7\json.hpp:line 918
   at 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>.get<int,int,0>(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>* ) in c:\users\dotlaptop\documents\visual studio 2015\projects\consoleapplication7\consoleapplication7\json.hpp:line 3193
   at 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>.operator<int,0>(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>* ) in c:\users\dotlaptop\documents\visual studio 2015\projects\consoleapplication7\consoleapplication7\json.hpp:line 3451
   at main() in c:\users\dotlaptop\documents\visual studio 2015\projects\consoleapplication7\consoleapplication7\consoleapplication7.cpp:line 54
   at _mainCRTStartup()

from_json<basic_json<>,int,0>(basic_json<>* j, Int32* val) in json.hpp:line 817 at from_json_fn.call<basic_json<>,int>(from_json_fn* , basic_json<>* j, Int32* val, priority_tag<1> __unnamed002) in json.hpp:line 856 at from_json_fn.operator()<basic_json<>,int>(from_json_fn* , basic_json<>* j, Int32* val) in json.hpp:line 871 at adl_serializer<int,void>.from_json<basic_json<> const &,int>(basic_json<>* j, Int32* val) in json.hpp:line 918 at basic_json<>.get<int,int,0>(basic_json<>* ) in json.hpp:line 3193 at basic_json<>.operator<int,0>(basic_json<>* ) in json.hpp:line 3451

What is the type of movieObject? This is in operator int(), so it looks like it's the assignment after the json::parse() call.

movieObject is a json object. I believe I tried it with auto, but perhaps not. I'll give that a try after I post this but here is a larger code snippet:

    Movie movies[5];
    int i;
    json movieObject;

    loadData(movies);

    printf("\n\nMy favorite movies are:\n----------\n\n");
    string amazonData = getAmazonData("Star Trek Beyond");
    string JSON = isolateJSON(&amazonData);
    printf("%s", JSON.c_str());
    try {
        movieObject = json::parse(JSON);
    }
    catch (exception& e) {
        printf("%s\n", e.what());
    }

Edit: I'm unable to get it to work with auto but that may be because I have no idea how to implement the auto class.

auto isn't a class, it means infer the type of the variable from the initializer. Since you don't have an initializer, you can't use auto. You would have to do

try {
    auto movieObject = json::parse(JSON);
}

but then you couldn't use movieObject after the try block.

Does the code above include line 54? If so, which line is that?

Huh, exactly like the readme? I think what happened there is that VS was giving me a red squiggly. In my troubleshooting, I must've split that away. But like you said earlier, the compiler may not understand and I should ignore that.

Anyway, now I get "type must be number, but is string"

Edit: And I moved line 54 into the try. It was this printf() that you see.

    Movie movies[5];
    int i;

    loadData(movies);

    printf("\n\nMy favorite movies are:\n----------\n\n");
    string amazonData = getAmazonData("Star Trek Beyond");
    string JSON = isolateJSON(&amazonData);

    try {
        auto movieObject = json::parse(JSON);
        printf("%d) %s.\n\tReleased in %d, received a rating of %.1f and is available on Amazon for $%.2f.\n\n", 1, movieObject["Title"], (int)movieObject["Year"], (double)movieObject["imdbRating"], 9.99);

    }
    catch (exception& e) {
        printf("%s\n", e.what());
    }
printf("%d) %s.\n\tReleased in %d, received a rating of %.1f and is available on Amazon for $%.2f.\n\n", 1, movieObject["Title"], (int)movieObject["Year"], (double)movieObject["imdbRating"], 9.99);

movieObject["Year"] and movieObject["imdbRating"] are both strings: "Year":"2016" "imdbRating":"7.1"

string title = movieObject["Title"];
string year = movieObject["Year"];
string rating = movieObject["imdbRating"];
printf("%d) %s.\n\tReleased in %s, received a rating of %s and is available on Amazon for $%.2f.\n\n", 1, title.c_str(), year.c_str(), rating.c_str(), 9.99);

gregmarr: Thank you so much, you've taught me a lot. We're not this far in the class yet, so this has been a great chance to learn. Thanks nlohmann for the library as well.

Good observation, @gregmarr.

Thanks @gregmarr for the support!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Prati369 picture Prati369  路  4Comments

afowles picture afowles  路  3Comments

asmaloney picture asmaloney  路  4Comments

bassosimone picture bassosimone  路  3Comments

alienzj picture alienzj  路  4Comments