Reputation: 51
I have an array of JSON objects similar to below:
[
{"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}
]
My application spits out a bunch of JSON objects that I need to add to a JSON file every 30 seconds lets say.
Each round I need to append to the same file and add new JSON objects to the array of JSON objects that I have. The first entry of each JSON file is the JSON schema.
The problem I am facing is that I do not know how to each time read the previous file and add new objects to the array of existing objects in file and write back the updated file.
Could you please provide me guidance as what needs to be done? or point me to couple of examples (couldn't find similar example in tutorial)?
Upvotes: 2
Views: 5888
Reputation: 3018
This post is from some years ago, but my answer is still relevant. I had the same problem as @SamZ. This answer improves the answer of @SamZ in several aspects:
Here is the code:
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;
}
Upvotes: 1
Reputation: 51
Assuming the current array of JSON objects on file is:
[{"one", "1"}, {"two", "2"}]
and we want to add a JSON object --> {"three", "3"} and write it back to the same file so that the final file looks like this: [{"one", "1"}, {"two", "2"}, {"three", "3"}]
Here is the list of complete steps to take:
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);
Upvotes: 3