我对代码有两个问题:
代码在第82行与断言IsString()崩溃。我不明白为什么因为该值应该是一个字符串。
我需要更智能地使用“动态”嵌套循环来浏览JSON数据。意思是:我希望有可能让代码根据在树中找到当前级别的对象来决定“生成”在更深层次上找到的对象,数组和字符串的新循环。由于JSON数据是通过我的主代码中的REST API通过CURL提取的,因此无法使用RAPIDJSON提供的指针。 JSON数据&拉结构不是静态的,可以改变。
代码应该做什么:浏览JSON字符串并解析所有对象,数组和字符串并打印它们。 JSON数据是嵌套的,包含一个“树”,它可以包含下面有更多对象的对象。 如果查看http://www.jsoneditoronline.org/?id=d9425ccdb8614d9b1fb8bc24a74cbfb0,您可以看到树结构,并且JSON字符串有效。
运行代码是必需的:来自github的RAPIDJSON的包含文件: https://github.com/miloyip/rapidjson
代码:
#include <stdio.h>
#include <string>
// RAPIDJSON -> https://github.com/miloyip/rapidjson/
#include <rapidjson/document.h>
#include <rapidjson/reader.h>
#include <rapidjson/writer.h>
#include <typeinfo>
int main()
{
// JSON String works -> http://www.jsoneditoronline.org/?id=d9425ccdb8614d9b1fb8bc24a74cbfb0
//
// Types:
// "" = string
// [] = array
// {} = object
//
std::string s = "{\"success\":1,\"data\":{\"species\":{\"rowcount\":6,\"totalrows\":\"6\",\"estimatedrows\":false,\"pagesize\":0,\"pagecount\":null,\"page\":1,\"offset\":0,\"startrow\":0,\"resultset\":[{\"id\":\"1\",\"name\":\"Nuts\",\"code\":\"NUT\"},{\"id\":\"2\",\"name\":\"Cachew\",\"code\":\"CHEW\"},{\"id\":\"3\",\"name\":\"Coconut\",\"code\":\"COCO\"}]},\"affiliations\":{\"rowcount\":6,\"totalrows\":\"6\",\"estimatedrows\":false,\"pagesize\":0,\"pagecount\":null,\"page\":1,\"offset\":0,\"startrow\":0,\"resultset\":[{\"id\":\"1\",\"name\":\"Ananas\",\"code\":\"NASS\",\"color\":\"#48bbd4\"},{\"id\":\"2\",\"name\":\"Kiwis\",\"code\":\"KIWI\",\"color\":\"#ffce17\"},{\"id\":\"3\",\"name\":\"Bananas\",\"code\":\"BANA\",\"color\":\"#bd002d\"}]}},\"code\":\"OK\",\"msg\":\"OK\"}";
// Create document
rapidjson::Document doc;
// Check for parsing errors
if (doc.Parse<0>(s.c_str()).HasParseError()) {
fprintf(stderr, "Failed to parse args: %s\n", s.c_str());
} else {
// Types
static const char* kt[] = { "Null", "False", "True", "Object", "Array", "String", "Number" };
// Loop through members
for (rapidjson::Value::ConstMemberIterator itr = doc.MemberBegin(); itr != doc.MemberEnd(); ++itr) {
fprintf(stderr, "member %s is a %s -> ", itr->name.GetString(), kt[itr->value.GetType()]);
switch (itr->value.GetType()) {
case rapidjson::kNullType: fprintf(stderr, "null"); break;
case rapidjson::kFalseType: fprintf(stderr, "False"); break;
case rapidjson::kTrueType: fprintf(stderr, "True"); break;
case rapidjson::kObjectType: fprintf(stderr, "Object"); break;
case rapidjson::kArrayType: fprintf(stderr, "size = %d", itr->value.Size()); break;
case rapidjson::kStringType: fprintf(stderr, "%s", itr->value.GetString()); break;
case rapidjson::kNumberType:
if (itr->value.IsInt())
fprintf(stderr, "%d", itr->value.GetInt());
else
fprintf(stderr, "%lf", itr->value.GetDouble());
break;
default: fprintf(stderr, "???"); break;
}
fprintf(stderr, "\n");
// Loops to dive deeper into objects - Need a smarter solution for dynamic nested loops
if (itr->value.GetType() == rapidjson::kObjectType) {
fprintf(stderr, "parse %s\n", itr->name.GetString());
for (rapidjson::Value::ConstMemberIterator itr2 = itr->value.MemberBegin(); itr2 != itr->value.MemberEnd(); ++itr2) {
fprintf(stderr, "member %s:%s is a %s\n", itr->name.GetString(), itr2->name.GetString(), kt[itr2->value.GetType()]);
if (itr2->value.GetType() == rapidjson::kObjectType) {
for (rapidjson::Value::ConstMemberIterator itr3 = itr2->value.MemberBegin(); itr3 != itr2->value.MemberEnd(); ++itr3) {
fprintf(stderr, "member %s:%s:%s is a %s\n", itr->name.GetString(), itr2->name.GetString(), itr3->name.GetString(), kt[itr3->value.GetType()]);
switch (itr3->value.GetType()) {
case rapidjson::kNullType: printf("%s=null\n", itr2->name.GetString()); break;
case rapidjson::kFalseType: printf("%s=False\n", itr2->name.GetString()); break;
case rapidjson::kTrueType: printf("%s=True\n", itr2->name.GetString()); break;
case rapidjson::kStringType: printf("%s=%s\n", itr2->name.GetString(), itr3->name.GetString()); break;
case rapidjson::kNumberType:
if (itr3->value.IsInt())
printf("%s=%d\n", itr2->name.GetString(), itr3->value.GetInt());
else
printf("%s=%lf\n", itr2->name.GetString(), itr3->value.GetDouble());
break;
case rapidjson::kArrayType:
{
// Values are of type string in JSON! WTF?!?
printf("%s=", itr2->name.GetString());
rapidjson::Value::ConstValueIterator itr4 = itr3->value.Begin();
//////////////////
printf("%s", itr4->GetString()); // BANG, BANG! She hits the ground..
for (++itr4; itr4 != itr3->value.End(); ++itr4) {
printf(",%s", itr4->GetString()); // Obviously she hits the ground too!
}
//////////////////
printf("\n");
}
break;
default: printf("???\n"); break;
}
}
}
}
}
}
}
return 0;
}
我不是C / C ++的专家,目前在这种情况下失败了。任何帮助解决我的2个问题都将非常感激。
我同时搜索了几天,以获得解决这个问题的想法,但没有成功。找到的解析示例仅处理没有子对象的“平面”JSON数据。