C++ RapidJSON-使用通配符迭代具有不同成员名称的复杂JSON结构
我有一个复杂的JSON要加载到C++11的数据结构中,我得到了关于RapidJSON的高度推荐。我需要迭代一个复杂的JSON,并四处寻找如何实现它的答案。我找到的最好的答案是 但是,将此解决方案与我的解决方案匹配时存在一个小问题,我在JSON中有不同名称但内容相同的成员:C++ RapidJSON-使用通配符迭代具有不同成员名称的复杂JSON结构,c++,json,rapidjson,C++,Json,Rapidjson,我有一个复杂的JSON要加载到C++11的数据结构中,我得到了关于RapidJSON的高度推荐。我需要迭代一个复杂的JSON,并四处寻找如何实现它的答案。我找到的最好的答案是 但是,将此解决方案与我的解决方案匹配时存在一个小问题,我在JSON中有不同名称但内容相同的成员: "responsibilities": { "starters_reciepe": { "name": "bok choi salad", "type": "veggie", "ingredient
"responsibilities": {
"starters_reciepe": {
"name": "bok choi salad",
"type": "veggie",
"ingredients": {
"leafyIng": "bok choi",
"proteinIng": "tofu",
"seasoning": [
{
"2 tsp": "salt",
"1 tsp": "turmric"
}
]
}
},
"mainCourse_reciepe": {
"name": "pad tai",
"type": "yum yum",
"ingredients": {
"leafyIng": "chard",
"proteinIng": "soylent green"
"seasoning": [
{
"2 tsp": "black pepper",
"1 tsp": "tears of the angels"
}
]
}
}
}
基本上,我需要检查一下配料的内容,但我不能忘记一个事实,即开胃菜和主菜不同
编辑:
这是我的密码:
Document d;
ifstream in("TestingJSON.json", ios::binary);
if (!in)
throw runtime_error("Failed to open file");
istreambuf_iterator<char> head(in);
istreambuf_iterator<char> tail;
string data(head, tail);
d.Parse(data.c_str());
const Value& prog = d["responsibilities"];
for (Value::ConstValueIterator p = prog.Begin(); p != prog.End(); ++p) {
cout << (*p)["iUniqueID"].GetString()<<endl;
const Value& inFiles = (*p)["inFiles"];
for (Value::ConstValueIterator inFile = inFiles.Begin(); inFile != prog.End(); ++inFile) {
cout << (*inFile)["sFileType"].GetString() << endl;
cout << (*inFile)["pos"]["x1"].GetInt() << endl;
}
}
文件d;
ifstream-in(“TestingJSON.json”,ios::binary);
如果(!in)
抛出运行时_错误(“打开文件失败”);
istreambuf_迭代器头(in);
istreambuf_迭代器尾部;
字符串数据(头、尾);
d、 解析(data.c_str());
const Value&prog=d[“责任”];
对于(Value::ConstValueIterator p=prog.Begin();p!=prog.End();++p){
cout如果您只需要检查字符串是否以已知值结尾,那么直接比较字符串非常简单,无需使用通配符库:
auto& obj = doc["responsibilities"];
std::string suffix = "_reciepe";
for (auto p = obj.MemberBegin(); p != obj.MemberEnd(); ++p) {
auto& member_name = p->name;
if (member_name.GetStringLength() >= suffix.length()) {
if (memcmp(member_name.GetString() + member_name.GetStringLength() - suffix.length(), suffix.c_str(), suffix.length()) == 0) {
// Process matching node
std::cout << p->value["name"].GetString() << std::endl;
}
}
}
auto&obj=doc[“职责”];
std::string suffix=“_receipe”;
对于(auto p=obj.MemberBegin();p!=obj.MemberEnd();++p){
自动&member\u name=p->name;
if(member_name.GetStringLength()>=后缀.length()){
if(memcmp(member_name.GetString()+member_name.GetStringLength()-后缀.length(),后缀.c_str(),后缀.length())==0){
//进程匹配节点
std::cout value[“name”]。GetString()始终使用linter(例如)验证原始JSON。您问题中的此JSON无效。您需要修复此问题
JSON中的“responsibilites”
对象仅包含配方。我不确定为什么需要将其与*\u配方进行比较。但是,考虑到下面的示例,如果需要,您可以轻松实现该比较。这在这方面可能会有所帮助
在这些迭代中,您可以使用C++11的基于范围的for循环。只需根据您的用例处理您要使用/操作的正确类型。如果有疑问,请参阅rapidjson和文档
下面是一个以原始文字字符串作为JSON输入的示例:
#include <iostream>
#include <rapidjson/document.h>
int main()
{
constexpr auto data = R"json(
{
"responsibilities": {
"starters_recipe": {
"name": "bok choi salad",
"type": "veggie",
"ingredients": {
"leafyIng": "bok choi",
"proteinIng": "tofu",
"seasoning": [{
"2 tsp": "salt",
"1 tsp": "turmric"
}]
}
},
"mainCourse_recipe": {
"name": "pad tai",
"type": "yum yum",
"ingredients": {
"leafyIng": "chard",
"proteinIng": "soylent green",
"seasoning": [{
"2 tsp": "black pepper",
"1 tsp": "tears of the angels"
}]
}
}
}
}
)json";
rapidjson::Document doc;
doc.Parse( data );
const auto& courses = doc["responsibilities"].GetObject();
for ( const auto& course : courses )
{
const auto& course_name = course.name.GetString();
const auto& recipe = courses[course_name].GetObject();
const auto& recipe_name = recipe["name"].GetString();
const auto& ingredients = recipe["ingredients"].GetObject();
const auto& leafyIng = ingredients["leafyIng"].GetString();
const auto& proteinIng = ingredients["proteinIng"].GetString();
const auto& seasoning = ingredients["seasoning"].GetArray()[0].GetObject();
std::cout << "Course: " << course_name << '\n'
<< "Recipe: " << recipe_name << '\n'
<< "Ingredients:\n"
<< "- Leaf : " << leafyIng << '\n'
<< "- Protein : " << proteinIng << '\n'
<< "- Seasoning:\n";
for ( const auto& s : seasoning )
{
const auto& k = s.name.GetString();
const auto& v = s.value.GetString();
std::cout << " - " << k << ", " << v << '\n';
}
std::cout << '\n';
}
return 0;
}
“调味”
数组只包含一个对象,这就是此行引用第0个索引的原因:
const auto& seasoning = ingredients["seasoning"].GetArray()[0].GetObject();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^
我猜您想要的是一个对象数组,而不是一个包含单个对象的数组
这:
而不是这个:
"seasoning": [{
"2 tsp": "black pepper",
"1 tsp": "tears of the angels"
}]
您还必须在代码中相应地处理它。看起来不错,但我尝试运行它,结果是:断言失败:IsObject(),文件c:\testingcode\rapidjson\document.h,第1285行testingcode.exe(进程90364)以代码3退出。我编辑了原始帖子并添加了我的代码。您发布的JSON无效。请使用在线linter进行检查,例如……并且,您发布的代码是您上面发布的代码的副本。它与您发布的JSON无关。您需要使用正确的代码更新正确的JSON。
"seasoning": [
{ "2 tsp": "black pepper" },
{ "1 tsp": "tears of the angels" }
]
"seasoning": [{
"2 tsp": "black pepper",
"1 tsp": "tears of the angels"
}]