Search code examples
c++rapidjson

How to modify nested rapidjson object on the fly?


All of the examples for rapidjson I can find for having nested objects are essentially as follows: 1) create root object 2) create nested object 3) build/add to nested object (root object so far unchanged) 4) once nested object is complete, add to root object

What I want to do at a high level: 1) create root object 2) create nested object and add to root object 3) build/add to nested object (root object inherently is updated as well, no need for further action)

This is so that if an exception is thrown while building the nested object, the step to add it to the root object was already completed, so I at least have the nested object partially built instead of completely missing.

Is this possible? Any assistance or insight will be greatly appreciated!


Solution

  • I was able to figure this out; however, since I haven't found documentation to support it, I'm not sure if I'm actually relying on any undefined or unsupported behavior.

    //Prepare 'root' object as a document
    rapidjson::Document document;
    rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
    document.SetObject();
    // 'document' currently serializes to {}
    
    //Create an empty rapidjson 'object' as a Value, and add it to root
    rapidjson::Value nestedObject(rapidjson::kObjectType);
    document.AddMember("Parent", nestedObject, allocator);
    // 'document' currently serializes to {"Parent":{}}
    
    /*Retrieve the 'object' as a Value
    This step is important! Trying to reuse the same 'nestedObject' Value from before
    without "re-retrieving" it will result in assertion errors at runtime.
    If you try to "re-retrieve" into the existing 'nestedValue' instance, the end
    result below will be {"Parent":null}*/
    rapidjson::Value &nestedObjectValue = document["Parent"];
    
    //Modify the 'nestedObjectValue'
    nestedObjectValue.AddMember("child", "child_value", allocator);
    // 'document' currently serializes to {"Parent":{"child":"child_value"}}
    

    Ultimately, this was the desired behavior I wanted. I have access to the nested object and can modify it at will and the changes will impact the root document.