[英]Retrieving a nested object inside a JSON string using rapidjson
我需要在 JSON 字符串中檢索嵌套對象,並且我正在嘗試使用 Rapidjson 來完成它。 我發現的只是如何檢索數組和基本類型,而不是子對象。 我創建了以下玩具示例,該示例出現錯誤:
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;
}
}
您需要手動遍歷對象的成員,因為 GetString() 僅適用於字符串成員,而 document["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;
}
此外,您可能想查看 Accept() 方法,它似乎返回您提供的對象的 JSON 字符串。
如果 element 是一個對象,您可以使用 [] 訪問子屬性:
for (SizeType i = 0; i < layers.Size(); i++){
cout << layers[i]["name"].GetString() << endl;
}
在 Rapidjson 中實現了另一種很棒的方法 - JSON Pointers 。 它們具有實驗狀態,根據文檔應包含在 v.1.1 中。 無論如何,這種方法看起來像 XML 的 XPATH,因此為了獲得嵌套值,我們可以使用類似的語法
Value* tmpValue = GetValueByPointer(doc, "/result/job/blob");
我嘗試了這個功能,在我看來這比迭代器更好。
您可以使用指針來獲取子對象:
Value& a = *GetValueByPointer(document, "/a");
int z = a["z"].GetInt();
GenericObject doc2 = document["a"].GetObjectW();
int z = doc2["z"].GetInt();
使用用於 C++ 的 RapidJson 庫解析 json 中嵌套對象的簡單方法..
這是將嵌套對象作為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;
}
您還可以使用 Document 的指針:
Document *document= new Document();
document->parse( test.c_str());
並放入值指針並使用它
Value *val= document;
val = &(*val)["a"];
val = &(*val)["z"];
cout << val->GetString();
這是我最近在做的事情:
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);
你完成了!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.