C++ 使用 Rapidjson 在 JSON 字符串中检索嵌套对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12742840/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Retrieving a nested object inside a JSON string using rapidjson
提问by pparescasellas
I need to retrieve a nested object inside a JSON string and I'm trying to do it using rapidjson. All I've found is how to retrieve arrays and basic types, but not sub-objects. I have created the following toy example which gives an error:
我需要在 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;
}
}
This is the output when executed:
这是执行时的输出:
{ "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
How do I retrieve the inner object to continue my parsing? Thanks.
如何检索内部对象以继续解析?谢谢。
Edit: What I need is to obtain the string representation of the inner object so I can call another function that is going to parse it.
编辑:我需要的是获取内部对象的字符串表示,以便我可以调用另一个要解析它的函数。
Edit 2: code that allows to retrieve the inner object as a string:
编辑 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;
}
}
采纳答案by Vesper
You need to iterate through object's members manually, as GetString() only works on string members, while document["a"] is an Object. You need to iterate through that object's members using MemberIterator variable. I had no practice in C* for more than 15 years, so I can only give a general idea of how it should work:
您需要手动遍历对象的成员,因为 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;
}
Also, you might want to look at Accept() method, it seems to return a JSON string of an object you give it.
此外,您可能想查看 Accept() 方法,它似乎返回您提供的对象的 JSON 字符串。
回答by lasote
If element is an object you can just access subproperties with []:
如果 element 是一个对象,您可以使用 [] 访问子属性:
for (SizeType i = 0; i < layers.Size(); i++){
cout << layers[i]["name"].GetString() << endl;
}
回答by Kostia Shiian
There is another great approach realized in rapidjson - JSON Pointers. They have experimental status and according to the documentation shall be included in v.1.1. Anyway this approach looks like XPATH for XML so to get nested value we can use syntax like
在 Rapidjson 中实现了另一种很棒的方法 - JSON Pointers。它们具有实验状态,根据文档应包含在 v.1.1 中。无论如何,这种方法看起来像 XML 的 XPATH,因此为了获得嵌套值,我们可以使用类似的语法
Value* tmpValue = GetValueByPointer(doc, "/result/job/blob");
I tried this functionality and in my opinion this is better than iterators.
我尝试了这个功能,在我看来这比迭代器更好。
回答by Michael
You can use a pointer to get the subobject:
您可以使用指针来获取子对象:
Value& a = *GetValueByPointer(document, "/a");
int z = a["z"].GetInt();
回答by RealityPC
Here is one example code to get the nested object as rapidjson::Document
object.
这是将嵌套对象作为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;
}
回答by Shubham Trigunait
you can also use the pointer of Document:
您还可以使用 Document 的指针:
Document *document= new Document();
document->parse( test.c_str());
and putting in the Value pointer and use it
并放入值指针并使用它
Value *val= document;
val = &(*val)["a"];
val = &(*val)["z"];
cout << val->GetString();
回答by a.raya203
This is something I recently worked on:
这是我最近在做的事情:
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
}
}
}
This can handle any type of JSON tree. All you have to do is pass a Value as such:
这可以处理任何类型的 JSON 树。您所要做的就是传递一个值:
Value v = document.GetObject();
Value& m= v;
enter(m);
And you're done!
你完成了!