iterate and retrieve nested object in JSON using rapidjson iterate and retrieve nested object in JSON using rapidjson json json

iterate and retrieve nested object in JSON using rapidjson


First, let me provide credit to MiloYip at this link

Second-- here's what I did for my project:

rapidjson::Document document;// document holds a json document retrieved from a http GET request// I did not include all of that in this example.  I am only showing// the part of iterating through a nested object and retrieving members.std::vector<std::string> symbols;// holds the values I retrieve from the json documentif (document.Parse<0>( symbol.c_str() ).HasParseError() )    Log() << "ERROR: encountered a JSON parsing error" << std::endl;else {    // Get the nested object that contains the elements I want.    // In my case, the nested object in my json document was results    // and the values I was after were identified as "t"    rapidjson::Value& results = document["results"];    assert(results.IsArray());    for (rapidjson::SizeType i = 0; i < results.Size(); i++) {        // Store the value of the element in a vector.        symbols.emplace_back(results[i]["t"].GetString());}                            

I think this is a pretty clean/efficient approach.


This is something I recently worked on:

void enter(const Value &obj, size_t indent = 0) { //print JSON treeif (obj.IsObject()) { //check if object    for (Value::ConstMemberIterator itr = obj.MemberBegin(); itr != obj.MemberEnd(); ++itr) {   //iterate through object           const Value& objName = obj[itr->name.GetString()]; //make object value        for (size_t i = 0; i != indent; ++i) //indent            cout << " ";        cout << itr->name.GetString() << ": "; //key name        if (itr->value.IsNumber()) //if integer            std::cout << itr->value.GetInt() ;        else if (itr->value.IsString()) //if string            std::cout << itr->value.GetString();        else if (itr->value.IsBool()) //if bool            std::cout << itr->value.GetBool();        else if (itr->value.IsArray()){ //if array            for (SizeType i = 0; i < itr->value.Size(); i++) {                if (itr->value[i].IsNumber()) //if array value integer                    std::cout << itr->value[i].GetInt() ;                else if (itr->value[i].IsString()) //if array value string                    std::cout << itr->value[i].GetString() ;                else if (itr->value[i].IsBool()) //if array value bool                    std::cout << itr->value[i].GetBool() ;                else if (itr->value[i].IsObject()){ //if array value object                    cout << "\n  ";                    const Value& m = itr->value[i];                     for (auto& v : m.GetObject()) { //iterate through array object                        if (m[v.name.GetString()].IsString()) //if array object value is string                            cout << v.name.GetString() << ": " <<   m[v.name.GetString()].GetString();                        else //if array object value is integer                            cout << v.name.GetString() << ": "  <<  m[v.name.GetString()].GetInt();                       cout <<  "\t"; //indent                    }                }                cout <<  "\t"; //indent            }        }        cout << endl;         enter(objName, indent + 1); //if couldn't find in object, enter object and repeat process recursively         }      } }

This can handle any type of JSON tree. All you have to do is pass a Value as such:

Value v = document.GetObject();Value& m= v;enter(m);

And you're done!


void parseRecursive(std::string scope                    , rapidjson::Value::ConstMemberIterator object                    , std::unordered_map<std::string, std::string>& values){    if (scope.empty())    {        scope = object->name.GetString();    }    else    {        scope = scope + "::" + object->name.GetString();    }    auto inElement = scope + "::";    if (object->value.IsObject())    {        for (auto it = object->value.MemberBegin(); it != object->value.MemberEnd(); ++it)        {            parseRecursive(scope, it, values);        }    }    else if (object->value.IsDouble())    {        values.emplace(inElement, std::to_string(object->value.GetDouble()));    }    else if (object->value.IsInt())    {        values.emplace(inElement, std::to_string(object->value.GetInt()));    }    else    {        LOGW("Unsuported: " << inElement << object->name.GetString());    }}

And start with document: rapidjson::Document document;

for (auto it = document.MemberBegin(); it != document.MemberEnd(); ++it){    parseRecursive("", it, _values);}