在 rapidjson 文档中搜索嵌套属性时不一致的 IsObject() 属性

Inconsistent IsObject() property in searching through nested properties in rapidjson document

我遇到一个问题,即 rapidjson 库在将 IsObject() 报告为 true 时似乎不一致。

有时 当我从 Document 中检索到 Value 后调用 value.IsObject() 时,它会正确地将其报告为 Object.但有时它会报告我认为应该是 Object 而不是 Object.

下面是一个玩具程序。

似乎我无意中以某种方式改变了文档,因为 vegetables::celery 的第二次查找明显失败了。

#define _CRT_SECURE_NO_DEPRECATE

#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
#include <string.h>
#include <stdio.h>
using namespace rapidjson;

int getInt(Document& jsonDoc, const char* propertyName)
{
    if (!jsonDoc.IsObject()) {
        puts("Err: jsonDoc not an object");
        return 0;
    }

    char* str = strdup(propertyName);
    char* p = strtok(str, ":");
    printf("Looking for property `%s`\n", p);
    if (!jsonDoc.HasMember(p))
    {
        printf("  - Error: %s not found, property %s\n", p, propertyName);
        free(str);
        return 0;
    }
    else
    {
        printf("  - found property '%s'\n", p);
    }

    rapidjson::Value& v = jsonDoc[p];
    
    while (p = strtok(0, ":"))
    {
        printf("Looking for property `%s`\n", p);
        if (v.IsObject())
        {
            puts("  - v is an object so I can look");
        }
        else
        {
            printf("  - ERROR: v is NOT an object, I can't search for %s, property %s not found\n", p, propertyName);
            free(str);
            return 0;
        }

        if (!v.HasMember(p))
        {
            printf("  - Error while digging: %s not found, property %s\n", p, propertyName);
            free(str);
            return 0;
        }
        else
            printf("  - found property '%s'\n", p);

        // otherwise,
        v = v[p];  // advance deeper into the tree
    }

    int val = v.GetInt();
    printf("  - json got value %s=%d\n", propertyName, val);
    free(str);
    return val;
}

void test1()
{
    const char* json = R"STR({
      "fruits":{
        "apples":1,
        "oranges":553,
        "bananas":900
      },
      "vegetables":{
        "celery":10000,
        "cabbage":10000
      }
    })STR";

    Document d;
    d.Parse(json);

    int apples = getInt(d, "fruits::apples");
    int oranges = getInt(d, "fruits::oranges");
    int bananas = getInt(d, "fruits::bananas");

    int celery = getInt(d, "vegetables::celery");
    celery = getInt(d, "vegetables::celery");
    int cabbage = getInt(d, "vegetables::cabbage");
}

int main()
{
    test1();
    return 0;
}

这里有两个问题。

第一和主要:

 rapidjson::Value& v = jsonDoc[p];
 ...
 v = v[p];  

因为v不是一个变量,而是一个reference,所以你没有将它设置为一个新的对象,而是改变了它引用的原始对象,破坏了它。

如果您需要更改下面的对象,请使用 rapidjsonPointers,或者您可以使用如下技巧:

 rapidjson::Value* v = &(jsonDoc[p]);
 ...
 v = &(*v)[p]; 

第二

在某些 returns 的 if-else 中,您有 str 的内存泄漏,您仅在函数结束时释放它。