rapidjson 在转换为字符串时产生不一致的结果

rapidjson producing inconsistent results when converting to string

我目前正在使用 JSON 序列化器 class。这是我正在研究的一些实验代码。此代码使用 cpprestsdk。序列化设置为使用 rapidjson 或 cpprestsdk 的 json。

例如,class 的虚函数如下所示:

virtual void toJson(rapidjson::Document& json) const =0;
virtual void toJson(web::json::value& json) const =0;

virtual void fromJson(const rapidjson::Value& json) =0;
virtual void fromJson(const web::json::value& json) =0;

我可以从 JSON 转换,没问题。我目前正在将 class 对象转换为 JSON,然后将其作为字符串导出到文件中。我发现使用 rapidjson,我得到了不同的结果。

在某些导出中,我看到这样的片段:

    "base": {
        "name\u0000refere": "base",

在其他运行中,我看到这样的片段:

    "base": {
        "name": "base",

这是针对连续运行的,没有更改代码。

这些字段实际上是全局定义的 const char * 如下所示:

const char *kSymbolKeyName = "name";
const char *kSymbolKeyReferenceName = "referenceName";

生成有问题的 JSON 对象的代码如下所示:

void Object::toJson(rapidjson::Document& json) const {
    using namespace rapidjson;

    json.SetObject();   // Reset and clear any existing

    auto& allocator = json.GetAllocator();

    json.AddMember(StringRef(kObjectKeyName), Value(name.c_str(), allocator), allocator);
    json.AddMember(StringRef(kObjectKeyPrioritizeTable), Value(prioritizeTable), allocator);
    json.AddMember(StringRef(kObjectKeyPrioritizeGreaterOn), Value(prioritizeGreaterOn), allocator);
}

请注意 kObjectKeyName 定义为 const char *kObjectKeyName = "name";

class 的 toJson 的调用者看起来像:

using namespace rapidjson;

json.SetObject();   // Reset and clear any existing

auto& allocator = json.GetAllocator();

for (const auto& it : tables) {
    Document iJson;
    it.second->toJson(iJson);
    json.AddMember(Value(it.first.c_str(), allocator), iJson, allocator);
}

部分问题可能源于我使用 rapidjson::Document 和分配器的方式。我相信一旦我进行 SetObject 调用,toJson 调用将以它自己的分配器结束。

我的计划是修改代码以在 toJson 中使用 Value 而不是 Document,然后将分配器作为参数传入。理想情况下我不想这样做主要是因为我很懒并且希望签名相同所以很容易在 rapidjson 或 cppsrestsdk 的儿子之间切换。

哦,是的,将文件输出为字符串的代码如下

        std::ofstream out("output.json");
        rapidjson::Document outDoc;

        dataSet.toJson(outDoc);

        rapidjson::StringBuffer buffer;

        buffer.Clear();

        rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
        outDoc.Accept(writer);
        out << buffer.GetString();

        out.close();

毫无疑问,我正在做的事情 odd/dumb 最近才开始使用 rapidjson。我只是想缩小我的问题范围并更好地理解我的方法的错误。

如果修改进程以传入分配器有效,它就会出现。

我将 toJson 函数修改为

    rapidjson::Value toJson(rapidjson::Document::AllocatorType& allocator);

在我的用法中,这意味着所有生成的 Value 将在需要时使用基础 Document 的分配器。