spiralstatic
spiralstatic

Reputation: 41

Parse JSON array using casablanca

I am trying to read from a JSON response in Casablanca. The sent data looks like this:

{
"devices":[
  {"id":"id1",
   "type":"type1"},
  {"id":"id2",
   "type":"type2"}
]
}

Does anyone know how to do this? Casablanca tutorials only seem to care about creating such arrays and not about reading from them.

Upvotes: 4

Views: 6813

Answers (2)

Aleksandr
Aleksandr

Reputation: 106

The following is a recursive function I made for parsing JSON values in cpprestsdk, if you would like additional info or elaboration feel free to ask.

std::string DisplayJSONValue(web::json::value v)
{
    std::stringstream ss;
    try
    {
        if (!v.is_null())
        {
            if(v.is_object())
            {
                // Loop over each element in the object
                for (auto iter = v.as_object().cbegin(); iter != v.as_object().cend(); ++iter)
                {
                    // It is necessary to make sure that you get the value as const reference
                    // in order to avoid copying the whole JSON value recursively (too expensive for nested objects)
                    const utility::string_t &str = iter->first;
                    const web::json::value &value = iter->second;

                    if (value.is_object() || value.is_array())
                    {
                        ss << "Parent: " << str << std::endl;

                        ss << DisplayJSONValue(value);

                        ss << "End of Parent: " << str << std::endl;
                    }
                    else
                    {
                        ss << "str: " << str << ", Value: " << value.serialize() << std::endl;
                    }
                }
            }
            else if(v.is_array())
            {
                // Loop over each element in the array
                for (size_t index = 0; index < v.as_array().size(); ++index)
                {
                    const web::json::value &value = v.as_array().at(index);

                    ss << "Array: " << index << std::endl;
                    ss << DisplayJSONValue(value);
                }
            }
            else
            {
                ss << "Value: " << v.serialize() << std::endl;
            }
        }
    }
    catch (const std::exception& e)
    {
        std::cout << e.what() << std::endl;
        ss << "Value: " << v.serialize() << std::endl;
    }

    return ss.str();
}

Upvotes: 7

davidhigh
davidhigh

Reputation: 15518

Let's assume you got your json as an http response:

web::json::value json;
web::http::http_request request;

//fill the request properly, then send it:

client
.request(request)
.then([&json](web::http::http_response response)
{
    json = response.extract_json().get();
})
.wait();

Note that no error checking is done here, so let's assume everything works fine (--if not,see the Casablanca documentation and examples).

The returned json can then be read via the at(utility::string_t) function. In your case it is an array (you either know that or check it via is_array()):

auto array = json.at(U("devices")).as_array();
for(int i=0; i<array.size(); ++i)
{
     auto id = array[i].at(U("id")).as_string();
     auto type = array[i].at(U("type")).as_string();
}

With this you get the entries of the json response stored in string variables.

In reality, you further might want to check whether the response has the coresponding fields, e.g. via has_field(U("id")), and if so, check whether the entries are not null via is_null() -- otherwise, the as_string() function throws an exception.

Upvotes: 14

Related Questions