使用 rapidjson 追加到文件中现有的 JSON 个对象数组

Append to an existing array of JSON objects on file using rapidjson

我有一个 JSON 对象数组,类似于以下内容:

[
    {"hello": "rapidjson",
    "t": true,
    "f": false,
    "n": null,
    "i": 2,
    "pi": 3.1416},
   {"hello": "rapidjson",
    "t": true,
    "f": false,
    "n": null,
    "i": 12,
    "pi": 3.88},
    {"hello": "rapidjson",
    "t": true,
    "f": false,
    "n": null,
    "i": 14,
    "pi": 3.99}
]

我的应用程序吐出一堆 JSON 对象,我需要每 30 秒将其添加到 JSON 文件中。

每一轮我都需要附加到同一个文件并将新的 JSON 个对象添加到我拥有的 JSON 个对象的数组中。每个 JSON 文件的第一个条目是 JSON 模式。

我面临的问题是我不知道如何每次读取以前的文件并将新对象添加到文件中现有对象的数组并写回更新后的文件。

能否请您指导我需要做什么?或者给我指出几个例子(在教程中找不到类似的例子)?

假设文件中 JSON 个对象的当前数组是:

[{"one", "1"}, {"two", "2"}]

并且我们要添加一个 JSON 对象 --> {"three", "3"} 并将其写回同一个文件,以便最终文件如下所示: [{ "one", "1"}, {"two", "2"}, {"three", "3"}]

这是要执行的完整步骤的列表:

using namespace rapidjson;

 FILE* fp = fopen(json_file_name.c_str(), "r");
 char readBuffer[65536];
 FileReadStream is(fp, readBuffer, sizeof(readBuffer));

 Document d, d2;
 d.ParseStream(is);
 assert(d.IsArray());
 fclose(fp);
 d2.SetObject();
 Value json_objects(kObjectType);
 json_objects.AddMember("three", "3", d2.GetAllocator());
 d.PushBack(json_objects, d2.GetAllocator());

 FILE* outfile = fopen(json_file_name.c_str(), "w");
 char writeBuffer[65536];
 FileWriteStream os(outfile, writeBuffer, sizeof(writeBuffer));

 Writer<FileWriteStream> writer(os);
 d.Accept (writer);
 fclose(outfile);

这个post是几年前的了,不过我的回答还是很贴切的。我和@SamZ 有同样的问题。这个答案在几个方面改进了@SamZ 的答案:

  1. 不需要读取或解析已经存在的文件
  2. 新对象直接添加到已经存在的文件中,不合并文档

代码如下:

bool appendToFile(const std::string& filename, const rapidjson::Document& document)
{
    using namespace rapidjson;
    
    // create file if it doesn't exist
    if (FILE* fp = fopen(filename.c_str(), "r"); !fp)
    {
        if (fp = fopen(filename.c_str(), "w"); !fp)
            return false;
        fputs("[]", fp);
        fclose(fp);
    }

    // add the document to the file
    if (FILE* fp = fopen(filename.c_str(), "rb+"); fp)
    {
        // check if first is [
        std::fseek(fp, 0, SEEK_SET);
        if (getc(fp) != '[')
        {
            std::fclose(fp);
            return false;
        }

        // is array empty?
        bool isEmpty = false;
        if (getc(fp) == ']')
            isEmpty = true;

        // check if last is ]
        std::fseek(fp, -1, SEEK_END);
        if (getc(fp) != ']')
        {
                std::fclose(fp);
                return false;
        }

        // replace ] by ,
        fseek(fp, -1, SEEK_END);
        if (!isEmpty)
            fputc(',', fp);

        // append the document
        char writeBuffer[65536];
        FileWriteStream os(fp, writeBuffer, sizeof(writeBuffer));
        Writer<FileWriteStream> writer(os);
        document.Accept(writer);

        // close the array
        std::fputc(']', fp);
        fclose(fp);
        return true;
    }
    return false;
}