2012-10-05 99 views
13

我需要检索JSON字符串内的嵌套对象,并试图使用rapidjson。我所找到的全部是如何检索数组和基本类型,但不是子对象。我已经创建了如下的玩具例子给出了一个错误:使用rapidjson检索JSON字符串中的嵌套对象

rapidjson::Document document; 
std::string test = " { \"a\": { \"z\" : 21 } } "; 
std::cout << test << std::endl; 
if (document.Parse<0>(test.c_str()).HasParseError()) { 
    std::cout << "Parsing error" << std::endl; 
} else { 
    if (document[ "a" ].IsObject()) { 
     std::cout << "OK" << std::endl; 
     std::cout << document[ "a" ].GetString() << std::endl; 
    } 
} 

这是执行时输出:

{ "a": { "z" : 21 } } 
OK 
JSONTest: ../rapidjson/document.h:441: const typename Encoding::Ch* rapidjson::GenericValue<Encoding, Allocator>::GetString() const [with Encoding = rapidjson::UTF8<char>, Allocator = rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>]: Assertion `IsString()' failed. Aborted 

如何检索内部对象继续我的分析?谢谢。

编辑:我需要的是获得内部对象的字符串表示,所以我可以调用另一个函数来解析它。

编辑2:代码,允许取回内对象的字符串:

rapidjson::Document document; 
std::string test = "{\"a\":{\"z\":21}} "; 
if (document.Parse<0>(test.c_str()).HasParseError()) { 
    std::cout << "Error parsing" << std::endl; 
} else { 
    if (document[ "a" ].IsObject()) { 
     rapidjson::StringBuffer sb; 
     rapidjson::Writer<rapidjson::StringBuffer> writer(sb); 
     document[ "a" ].Accept(writer); 
     std::cout << sb.GetString() << std::endl; 
    } 
} 
+0

这是否意味着RapidJson不支持分层对象?所以它只解析根级?!?! –

回答

7

您需要通过对象的成员手动迭代,如getString()只适用于字符串的成员,而文档[ “a”]是一个对象。您需要使用MemberIterator变量遍历该对象的成员。我在C *没有实践过超过15年,所以我只能给它应该如何工作总体思路:

for (MemberIterator m = document["a"].MemberBegin(); m != document["a"].MemberEnd(); ++m) { 
    std::cout << m.name << " " << (m.IsNumber()?m.GetNumber():m.GetString()) << endl; 
} 

此外,您可能想看看accept()方法,它似乎返回一个你给它的对象的JSON字符串。

+0

是的,“Accept()”就是答案。它允许将内部对象放入填充字符缓冲区的作者。然后,可以从缓冲区获取字符串。我用一个工作代码编辑了原始问题。非常感谢! – pparescasellas

3

如果元素是一个对象,你可以访问子属性与[]:

for (SizeType i = 0; i < layers.Size(); i++){ 
    cout << layers[i]["name"].GetString() << endl; 
} 
-1

下面是一个例子代码来获取嵌套的对象rapidjson::Document对象。

Document get_nested(Document &d, std::string key){ 
rapidjson::StringBuffer buffer; 
const char *key_ctr = key.c_str(); 

assert(d[key_ctr].IsObject()); 

rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); 
d[key_ctr].Accept(writer); 

rapidjson::Document result; 
rapidjson::StringStream s(buffer.GetString()); 
result.ParseStream(s); 

return result; 
} 
-1

你也可以使用文件的指针:

Document *document= new Document(); 
document->parse(test.c_str()); 

和投入的价值指针,并用它

Value *val= document; 
val = &(*val)["a"]; 
val = &(*val)["z"]; 
cout << val->GetString(); 
-3

这是我最近的工作:

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 
    }  
} 
} 

这可以处理任何类型的JSON树。所有你需要做的就是传递一个价值:

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

你完成了!

+1

你只是在所有quickjson问题上粘贴相同的答案? downvote –

+1

我在网上永远看着这个,找不到它。只是想帮助。冷静 –

相关问题