简体   繁体   中英

rapidjson producing inconsistent results when converting to string

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM