我需要在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;
}
}
答案 0 :(得分:7)
您需要手动迭代对象的成员,因为GetString()仅适用于字符串成员,而document [“a”]是Object。您需要使用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字符串。
答案 1 :(得分:3)
如果element是一个对象,你可以使用[]:
访问子属性for (SizeType i = 0; i < layers.Size(); i++){
cout << layers[i]["name"].GetString() << endl;
}
答案 2 :(得分:1)
在Rapidjson中实现了另一种很棒的方法-JSON Pointers。它们具有实验状态,并且根据文档应包含在v.1.1中。无论如何,这种方法看起来像XML的XPATH,因此要获取嵌套值,我们可以使用
这样的语法Value* tmpValue = GetValueByPointer(doc, "/result/job/blob");
我尝试了此功能,我认为这比迭代器要好。
答案 3 :(得分:0)
您可以使用指针来获取子对象:
Value& a = *GetValueByPointer(document, "/a");
int z = a["z"].GetInt();
答案 4 :(得分:0)
GenericObject doc2 = document["a"].GetObjectW();
int z = doc2["z"].GetInt();
使用用于 C++ 的 RapidJson 库解析 json 中嵌套对象的简单方法..
答案 5 :(得分:-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;
}
答案 6 :(得分:-1)
你也可以使用Document的指针:
Document *document= new Document();
document->parse( test.c_str());
并输入Value指针并使用它
Value *val= document;
val = &(*val)["a"];
val = &(*val)["z"];
cout << val->GetString();
答案 7 :(得分:-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:
Value v = document.GetObject();
Value& m= v;
enter(m);
你已经完成了!