Как сериализовать объект json, не заключая его в подобъект, используя Cereal

Допустим, у меня есть класс в C ++, например:

struct Point {
int x, y, z;
};

Я хочу использовать Cereal для сериализации этой структуры в JSON. Поэтому я добавил функцию сериализации следующим образом:

struct Point {
int x, y, z;
template<class Archive>
void serialize(Archive& ar) {
ar(CEREAL_NVP(x),
CEREAL_NVP(y),
CEREAL_NVP(z));
}
};

Это прекрасно работает, когда Point является членом другого объекта или элемента массива. Но если я хочу сделать Point основным объектом всего файла JSON, он не будет работать должным образом. Например, с помощью следующего кода:

Point p { 1, 2, 3 };
cereal::JSONOutputArchive ar(std::cout);
ar(p);

Я получаю следующий вывод:

{
"value0": {
"x": 1,
"y": 2,
"z": 3
}
}

Я хотел бы удалить "value0" ключ и поднять объект, чтобы занять весь файл, как это:

{
"x": 1,
"y": 2,
"z": 3
}

Единственный способ, которым я могу это сделать, — это заново реализовать функцию сериализации, добавив имена ключей вручную.

Point p {1, 2, 3};
cereal::JSONOutputArchive ar(std::cout);
ar(cereal::make_nvp("x", p.x),
cereal::make_nvp("y", p.y),
cereal::make_nvp("z", p.z));

Есть ли способ сделать это, используя функцию сериализации, которую я уже реализовал для класса?

2

Решение

Ладно, разобрался. Довольно просто, просто нужно вызвать функцию сериализации непосредственно из объекта, передавая архив, а не передавая объект в архив.

Point p {1, 2, 3};
cereal::JSONOutputArchive ar(std::cout);
p.serialize(ar);
5

Другие решения

Ответ Бенджамина — идеальное решение, если вы заранее знаете, что сериализуемый класс имеет serialize() метод. Так как Cereal поддерживает в классе / вне класса serialize(), Трещина load()/save()явное управление версиями; это не всегда так. Зерновые внутренние cereal::InputArchive а также cereal::OutputArchive оба класса имеют набор шаблонных методов SFINAE для определения правильного метода сериализации, используемого во время компиляции. Тип-черты могут быть использованы для переключения нашего собственного шаблона:

template< typename Class, typename Archive,
typename std::enable_if< cereal::traits::has_member_serialize<Class, Archive>::value>::type* = nullptr>
inline static void serializeHelper(Class& cl, Archive& ar)
{
cl.serialize(ar);
}

template< typename Class, typename Archive,
typename std::enable_if< cereal::traits::has_member_save<Class, Archive>::value>::type* = nullptr>
inline static void serializeHelper(Class& cl, Archive& ar)
{
cl.save(ar);
}

// More version could follow for remaining serialization types (external, versioned...)

template< typename Class, typename Archive,
typename std::enable_if< cereal::traits::has_member_serialize<Class, Archive>::value>::type* = nullptr>
inline static void deserializeHelper(Class& cl, Archive& ar)
{
cl.serialize(ar);
}

template< typename Class, typename Archive,
typename std::enable_if< cereal::traits::has_member_load<Class, Archive>::value>::type* = nullptr>
inline static void deserializeHelper(Class& cl, Archive& ar)
{
cl.load(ar);
}

// More version could follow for remaining deserialization types (external, versioned...)

призвание serializeHelper(p, ar); автоматически выберет метод сериализации, предоставленный Pointтак же, как Cereal делает внутренне.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector