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"s jsonDocument со случайным значением поля (в этом случае rapidjson::kNullType) и после этого, чтобы CopyFrom WheelСоответствующий документ.

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

1 ответ

Решение

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

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

rapidjson::Document jsonSubDocument(&jsonDocument.GetAllocator());
wheel_.ToJson(jsonSubDocument);
jsonDocument.AddMember("wheel_", jsonSubDocument, jsonDocument.GetAllocator());
Другие вопросы по тегам