使用rapidjson迭代并检索JSON中的嵌套对象

Rut*_*raj 6 c++ json rapidjson

我正在解析一个JSON类似如下的结构

{
    "item1" : "value1"
    "item2" : "value2"
    // ...
    "itemn" : {
        "outernestedItem1" : {
            "innerNestedItem1" : "valuen1"
            "innerNestedItem2" : "valuen2"
        }
        // ....
        "outernestedItemn" : {
            "innerNestedItem1" : "valuen1"
            "innerNestedItem2" : "valuen2"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

外部嵌套项的数量不固定,所以我使用来自rapidjson的迭代器进行迭代,内部嵌套对象变量是固定的,所以我可以使用[]来访问它们.

const rapidjson::Value& itemn = document["itemn"];
for (rapidjson::Value::ConstMemberIterator itr = itemn.MemberBegin();
itr != itemn.MemberEnd(); ++itr)
{
    rapidjson::StringBuffer sb;
    rapidjson::Writer<rapidjson::StringBuffer> writer( sb );
    itr->value.Accept(writer);

    std::cout << sb["innerNestedItem1"].GetString();
    std::cout << sb["innerNestedItem2"].GetString();
}
Run Code Online (Sandbox Code Playgroud)

但是sb(字符串缓冲区)不允许[],任何想法我怎么能这样做?

编辑1:我以非常低效的方式做到了,但只是共享解决方案,所以它可能有助于某人提出有效的解决方案.

const rapidjson::Value& itemn = document["itemn"];
for (rapidjson::Value::ConstMemberIterator itr = itemn.MemberBegin();
itr != itemn.MemberEnd(); ++itr)
{
    rapidjson::StringBuffer sb;
    rapidjson::Writer<rapidjson::StringBuffer> writer( sb );
    itr->value.Accept(writer);

    //changed from here onwards
    rapidjson::Document for_outer_nested_item;
    std::string temp = sb.GetString();
    char buffer2[100000];
    strcpy_s(buffer2, temp.c_str());
    for_outer_nested_item.ParseInsitu(buffer2);
    std::cout << executive_command["innerNestedItem1"].GetString() << std::endl;
    std::cout << executive_command["innerNestedItem2"].GetString() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

TGa*_*ord 7

首先,让我通过此链接向MiloYip提供信贷

第二 - 这就是我为我的项目所做的事情:

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 document

if (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());
}                            
Run Code Online (Sandbox Code Playgroud)

我认为这是一种非常干净/高效的方法.


小智 6

这是我最近从事的工作:

void enter(const Value &obj, size_t indent = 0) { //print JSON tree

if (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 
        }     
 }
 }
Run Code Online (Sandbox Code Playgroud)

这可以处理任何类型的JSON树。您要做的就是传递一个Value,例如:

Value v = document.GetObject();
Value& m= v;
enter(m);
Run Code Online (Sandbox Code Playgroud)

大功告成!

  • 我尝试了你的解决方案,但是:`Value v = document.GetObject();`给了我`错误:'rapidjson::Document {aka class rapidjson::GenericDocument&lt;rapidjson::UTF8&lt;&gt; &gt;}'没有名为'的成员获取对象'` (2认同)