C ++& RAPIDJSON:需要智能“动态嵌套循环”

时间:2017-02-21 16:58:08

标签: c++ json nested-loops rapidjson

我对代码有两个问题:

  1. 代码在第82行与断言IsString()崩溃。我不明白为什么因为该值应该是一个字符串。

  2. 我需要更智能地使用“动态”嵌套循环来浏览JSON数据。意思是:我希望有可能让代码根据在树中找到当前级别的对象来决定“生成”在更深层次上找到的对象,数组和字符串的新循环。由于JSON数据是通过我的主代码中的REST API通过CURL提取的,因此无法使用RAPIDJSON提供的指针。 JSON数据&拉结构不是静态的,可以改变。

  3. 代码应该做什么:浏览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数据。

0 个答案:

没有答案