2012-10-05 3 views
13

JSON 문자열에서 중첩 된 객체를 가져와야하고 rapidjson을 사용하여이를 수행하려고합니다. 내가 찾은 것은 배열과 기본 유형을 검색하는 방법이지만 하위 객체는 검색하지 않는 것입니다. 내 구문 분석을 계속 내부 개체를 검색하려면 어떻게rapidjson을 사용하여 JSON 문자열 내에서 중첩 된 객체 검색

{ "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 

:

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

이 실행 출력이 : 나는 오류가 제공하는 다음과 같은 장난감 예를 만들었습니다? 감사.

편집 : 필요한 것은 내부 개체의 문자열 표현을 가져 와서 구문 분석 할 다른 함수를 호출 할 수 있습니다.

편집 2 : 문자열로 내부 객체를 검색 할 수 있습니다 코드 :

당신하여 GetString()가 전용 문서하면서, 선재에서 작동하기 때문에, 수동으로 개체의 멤버를 반복 할 필요가
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

[ "a"는 객체입니다. MemberIterator 변수를 사용하여 해당 객체의 멤버를 반복해야합니다. 나는 15 년 이상 C *에는 연습을했다, 그래서 나는 단지 그것이 작동하는 방법의 일반적인 아이디어를 제공 할 수 있습니다 : 또한

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

, 당신은의() 메소드를 수락 볼 수도 있습니다를, 그것은 보인다 사용자가 지정한 객체의 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

모든 rapidjson 질문에 동일한 답변을 붙이고 있습니까? downvote –

+1

나는 인터넷에서 영원히 이것을 보았고 찾을 수 없었다. 그냥 도와 주려고. 진정해 –