I currently have a JSON serializer class that I'm using. It's for some experimental code that I'm working on. This code is using cpprestsdk. The serialization is setup to use either rapidjson or cpprestsdk's json.
So for example, the virtual functions for the class look like:
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;
I can convert from JSON no problem. I'm currently doing the conversion of a class object to JSON, and then exporting it as a string to a file. I have found that with rapidjson, I get variable results.
On some exports, I see a snippet like this:
"base": {
"name\u0000refere": "base",
On other runs, I see a snippet like this:
"base": {
"name": "base",
This is for successive runs, with no changes to the code.
The fields are actually globally defined const char *
like so:
const char *kSymbolKeyName = "name";
const char *kSymbolKeyReferenceName = "referenceName";
The code to generate the JSON object that has the issue looks like:
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);
}
Note that kObjectKeyName
is defined as const char *kObjectKeyName = "name";
.
And the caller to this class's toJson
would look like:
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);
}
Part of the problem may stem from the way I am using rapidjson::Document
s and allocators. I believe toJson
call will end up with it's own allocator once I make the SetObject
call.
My plan is to revamp the code to use Value
instead of Document
in toJson
and then pass the allocator in as an argument. I ideally didn't want to do that mainly because I was being lazy and wanted the signature to the same so it was easy to flip between rapidjson or cppsrestsdk's son.
Oh yeah, the code to output the file as a string is the following
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();
There is no doubt something that I am doing odd/dumb as just recently started using rapidjson. I'm just trying to narrow down my issues and better understand the error of my ways.
It appears if modifying the process to pass in an allocator works.
I modified my toJson
function to be
rapidjson::Value toJson(rapidjson::Document::AllocatorType& allocator);
In my usage, it means all generated Value
s, when needed, will use the base Document
's allocator.