'parse libcurl response with nlohmann json or rapidjson
My libcurl code returns me a json string:
{"object":"user","attributes":{"id":000,"admin":false,"username":"un","email":"[email protected]","first_name":"leopold95","last_name":"leopold95","language":"en"}}
I want parse this string in my objects (my problem isn't in it). But when I try parsing this with nlohmann or rapid I am getting an error. But if I try parse this string:
string str = "{\"object\":\"user\",\"attributes\":{\"id\":36,\"admin\":false,\"username\":\"a4qsmr9m\",\"email\":\"[email protected]\",\"first_name\":\"leopold95\",\"last_name\":\"leopold95\",\"language\":\"en\"}}";
with nlohmann everything works fine. With rapid I do not get any errors either.
So, my question is:
How can I parse the first string with nlohmann ?
or
How could I replace all " with \" in my response?
And, of course replace(s, "", ""); replace(s, '', ''); , replace(s.begin(), s.end(), ""/'', ""/'');
don't work for me. In some situations I have my "replaced symbols" at the end of the string
If needed I can add more code or publish the project to git
EDIT:
UserInfo Engine::testIU(string link)
{
    CURL* curl;
    CURLcode res;
    string readBuffer;
    curl = curl_easy_init();
    struct curl_slist* headers = NULL; //headers struct
    if (curl) {
        //headers = curl_slist_append(headers, "Content-Type: application/json");
        headers = curl_slist_append(headers, "Accept: application/json");
        headers = curl_slist_append(headers, "Authorization: Bearer imr8VuU9L6qUTjyZQ0srCNyfFE7Ru0v8VOLZBMd8bhjxJFfP");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); //add headers
        curl_easy_setopt(curl, CURLOPT_URL, link.c_str());   //set url
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); //set http method
        //curl_easy_setopt(curl,CURLOPT_RETURNTR, true);
        //curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, &readBuffer); /* data goes here */
        res = curl_easy_perform(curl);
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    json j = json::parse(readBuffer);
    testUserI.id = j["attributes"]["id"].get<int>();
    testUserI.admin = j["attributes"]["admin"].get<bool>();
    testUserI.username = j["attributes"]["username"].get<string>();
    testUserI.email = j["attributes"]["email"].get<string>();
    return testUserI;
}
struct UserInfo
{
    int id = 0;
    bool admin = NULL;
    string username = "";
    string email = "";
    string first_name = "";
    string last_name = "";
};
{"object":"user","attributes":{"id":0,"admin":false,"username":"a4qsmr9m","email":"[email protected]","first_name":"leopold95","last_name":"leopold95","language":"en"}}
EDIT 2: so if you have the same problem just fix this in your code:
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
and see answer above and all comments there
Solution 1:[1]
The json.exception.parse_error you get is due to the fact that "id":000 not valid JSON. It should most likely be "id":0.
The proper way to fix this is to ask the other end to correct the mistake.
How could I replace all
"to\"in my respose?
That wouldn't help and would in fact make the JSON even more invalid. The \ in your initialization of str does not become a part of the string and the only reason why you think that works is because the id field, "id":36, in that string is valid. Replace it with "id":000 and you will see that it will fail to parse that too.
A note on the added curl code. The below isn't correct and will cause undefined behavior:
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, &readBuffer);
The argument to CURLOPT_POSTFIELDS should be a char*, not a std::string*. Remove that option if you're not using it for posting.
You need to supply the std::string* via CURLOPT_WRITEDATA and cast it back to a std::string& in your CURLOPT_WRITEFUNCTION callback.
Example:
size_t WriteCallback(char* ptr, size_t size, size_t nmemb, void* userdata) {
    std::string& buf = *static_cast<std::string*>(userdata);
    buf.append(ptr, std::next(ptr, nmemb * size));
    return nmemb * size;
}
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
For testing you don't have to escape all the " with backslashes, just use a raw string literal.
Example: (change "id":000 to "id":0 and it'll work)
#include <nlohmann/json.hpp>
#include <iostream>
#include <string>
using json = nlohmann::json;
int main() {
    std::string str =
        R"aw({"object":"user","attributes":{"id":000,"admin":false,"username":"un","email":"[email protected]","first_name":"leopold95","last_name":"leopold95","language":"en"}})aw";
    try {
        auto j = json::parse(str);
        std::cout << j.dump(2) << '\n';
    } catch(const json::exception& ex) {
        std::cerr << "Parse error: " << ex.what() << '\n';
    }
}
Output:Parse error: [json.exception.parse_error.101] parse error at line 1, column 38: syntax error while parsing object - unexpected number literal; expected '}'
Output with the error fixed:
{
  "attributes": {
    "admin": false,
    "email": "[email protected]",
    "first_name": "leopold95",
    "id": 0,
    "language": "en",
    "last_name": "leopold95",
    "username": "un"
  },
  "object": "user"
}
With the input in your edited question:
std::string str =
    R"aw({"object":"user","attributes":{"id":36,"admin":false,"username":"a4qsmr9m","email":"[email protected]","first_name":"leopold95","last_name":"leopold95","language":"en"}})aw";
It would be successfully parsed and the program above would print:
{
  "attributes": {
    "admin": false,
    "email": "[email protected]",
    "first_name": "leopold95",
    "id": 36,
    "language": "en",
    "last_name": "leopold95",
    "username": "a4qsmr9m"
  },
  "object": "user"
}
    					Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | 
