Rapidjson: добавить в документ внешний субдокумент

Я хочу сериализовать вложенную структуру в JSON с помощью Rapidjson, и я также хочу иметь возможность сериализовать каждый объект отдельно, чтобы любой класс, реализующий ToJson, можно было сериализовать в строку JSON.

В следующем коде Car имеет член Wheel, и оба класса реализуют метод ToJson, который заполняет rapidjson::Document всеми их членами. Этот метод вызывается из шаблона функции ToJsonString для получения отформатированной строки JSON переданного объекта.

#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"

template<typename T> std::string ToJsonString(const T &element)
{
    rapidjson::StringBuffer jsonBuffer;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> jsonWriter(jsonBuffer);
    rapidjson::Document jsonDocument;
    element.ToJson(jsonDocument);
    jsonDocument.Accept(jsonWriter);

    return jsonBuffer.GetString();
}

struct Wheel
{
    std::string brand_;
    int32_t diameter_;

    void ToJson(rapidjson::Document &jsonDocument) const
    {
        jsonDocument.SetObject();
        jsonDocument.AddMember("brand_", brand_, jsonDocument.GetAllocator());
        jsonDocument.AddMember("diameter_", diameter_, jsonDocument.GetAllocator());
    }
};

struct Car
{
    std::string brand_;
    int64_t mileage_;
    Wheel wheel_;

    void ToJson(rapidjson::Document &jsonDocument) const
    {
        jsonDocument.SetObject();
        jsonDocument.AddMember("brand_", brand_, jsonDocument.GetAllocator());
        jsonDocument.AddMember("mileage_", mileage_, jsonDocument.GetAllocator());

        rapidjson::Document jsonSubDocument;
        wheel_.ToJson(jsonSubDocument);
        jsonDocument.AddMember("wheel_", rapidjson::kNullType, jsonDocument.GetAllocator());
        jsonDocument["wheel_"].CopyFrom(jsonSubDocument, jsonDocument.GetAllocator());
    }
};

Как видите, Car::ToJson вызывает Wheel::ToJson, чтобы получить описание Wheel и добавить его в качестве подобъекта, но я не мог придумать приемлемого решения для этого из-за управления распределением (я также читал другие вопросов).

Обходной путь, который я нашел, заключается в добавлении члена в Car jsonDocument со случайным значением поля (в данном случае rapidjson::kNullType), а затем в CopyFrom соответствующий документ Wheel.

Как я могу это сделать?


person Alexandru Irimiea    schedule 01.10.2015    source источник


Ответы (1)


Это оказалось проще, чем я думал. Из GitHub (проблема 436):

Самое простое решение избежать копирования - повторно использовать распределитель внешнего документа:

rapidjson::Document jsonSubDocument(&jsonDocument.GetAllocator());
wheel_.ToJson(jsonSubDocument);
jsonDocument.AddMember("wheel_", jsonSubDocument, jsonDocument.GetAllocator());
person Alexandru Irimiea    schedule 03.10.2015