1

I've got the following json string:

{
    "data" : 
    [
        {
            "cart" : "[{\"name\":\"Test item 1\",\"price\":15,\"quantity\":1,\"sum\":15,\"tax\":\"none\",\"payment_type\":\"advance\",\"item_type\":\"service\"},{\"name\":\"Test item 2\",\"price\":13.01,\"quantity\":2,\"sum\":26.02,\"tax\":\"none\",\"payment_type\":\"part_prepay\",\"item_type\":\"work\"}]",
            "contact" : "noname@google.com",
            "p_id" : "603",
            "sum" : "100.02",
            "tax_system" : "osn"
        }
    ],
    "msg" : null,
    "result" : "success"
}

I can parse cart as std::string after parsing input json string as stringstream:

const std::string ParseJsonData(std::stringstream ssJsonStream)
{
    Json::Value jsonData;
    Json::Value responseData;
    Json::Value responseDataCart;
    Json::CharReaderBuilder jsonReader;
    std::string errs;

    if (Json::parseFromStream(jsonReader, ssJsonStream, &jsonData, &errs)) {
        responseData = jsonData["data"];
        responseDataCart = responseData[0]["cart"];
        return responseDataCart.toStyledString().c_str();
    }
    else
        return "Could not parse HTTP data as JSON";
}

Please, tell me, how can i parse cart as array with JsonCpp?

Michael K.
  • 11
  • 2
  • Did you try `responseDataCart = responseData[0]["cart"]["name"];` – Duck Dodgers Jan 02 '19 at 12:29
  • Yes, i tried - it doesn't work. – Michael K. Jan 02 '19 at 12:30
  • Your return statement is wasteful. `toStyledString()` already gives you a `std::string`, which only needs directly returning (which will move it); you're obtaining a C-string out of it then constructing a new string from _that_. It's not the end of the world, but it does require a `strlen` invocation and prohibits moving the data. – Lightness Races in Orbit Jan 02 '19 at 12:42

1 Answers1

2

The same way you parsed the outer JSON!

You started with a string (well, hidden by a stream) and turned it into JSON.

Now that JSON contains a property that is a string and, itself, contains JSON. The problem is recursive. The fact that the inner string originally came from JSON too can be ignored. Just pretend it's a string you typed in.

So, you can use JSON::Reader to in turn get the JSON out of that string.

Something like:

const std::string responseDataCartStr = responseData[0]["cart"].asString();

Json::Reader reader;
if (!reader.parse(responseDataCartStr, responseDataCart))
   throw std::runtime_error("Parsing nested JSON failed");

JsonCpp provides a few ways to parse JSON and it's worth exploring them to find the most appropriate for your use case. The above is just an example.

Ignore the backslashes — the escaping was meaningful within the encapsulating JSON document, but the outermost parse stage should already have taken that into consideration. You'll see if you print responseDataCartStr to console that it is a valid JSON document in its own right.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Thanks a lot for the reply! Works perfectly with Json::CharReader* reader = jsonReader.newCharReader(); – Michael K. Jan 02 '19 at 13:50
  • @MichaelK. Don't forget to `delete` it! I like to use `std::unique_ptr` for the task. I had a memory leak in production where I was doing `auto reader = Json::CharReaderBuilder().newCharReader();` and forgot that it returns a naked pointer :( Needless to say that area of code now has a massive comment warning slapped all over it – Lightness Races in Orbit Jan 02 '19 at 13:52