Сериализация объектов в C++: обзор инструментов и библиотек
Сериализация — это процесс преобразования сложных структур данных (объектов, массивов, графов) в линейный формат (байтовый поток, строку JSON, XML), который можно сохранить в файл, передать по сети или записать в базу данных. Обратный процесс — десериализация — восстанавливает исходное состояние объекта. В C++ нет встроенной поддержки рефлексии (как в Java или Python), поэтому для сериализации приходится либо писать код вручную, либо использовать готовые библиотеки. В этой статье мы разберём самые популярные и эффективные инструменты для сериализации в C++.
1. Boost.Serialization
Старейшая и наиболее мощная библиотека. Входит в состав Boost, требует установки отдельно. Поддерживает бинарную, текстовую (XML) и собственную портативную архивацию.
- Преимущества: глубокая поддержка STL, умных указателей, полиморфизма, циклических ссылок; версионность; совместимость между разными платформами.
- Недостатки: громоздкий синтаксис, медленная компиляция, большой размер исполняемого файла.
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <fstream>
#include <vector>
struct Person {
std::string name;
int age;
std::vector<std::string> tags;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & name;
ar & age;
ar & tags;
}
};
int main() {
Person p{"Alice", 30, {"developer", "cpp"}};
std::ofstream ofs("person.txt");
boost::archive::text_oarchive oa(ofs);
oa << p;
// Десериализация
Person restored;
std::ifstream ifs("person.txt");
boost::archive::text_iarchive ia(ifs);
ia >> restored;
return 0;
}
2. Cereal
Современная, лёгкая, header-only библиотека (не требует сборки). Работает с C++11 и выше. Поддерживает JSON, XML и бинарные форматы. Очень популярна в игровой индустрии и embedded-разработке.
- Преимущества: минимальные накладные расходы, интуитивный API, поддержка умных указателей, полиморфизма, контейнеров STL.
- Недостатки: меньше возможностей для кастомизации, чем у Boost.
#include <cereal/archives/json.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/types/string.hpp>
#include <sstream>
struct Person {
std::string name;
int age;
template<class Archive>
void serialize(Archive & ar) {
ar(CEREAL_NVP(name), CEREAL_NVP(age));
}
};
int main() {
Person p{"Bob", 25};
std::ostringstream oss;
{
cereal::JSONOutputArchive archive(oss);
archive(CEREAL_NVP(p));
}
std::cout << oss.str() << std::endl;
// Десериализация
Person restored;
std::istringstream iss(oss.str());
{
cereal::JSONInputArchive archive(iss);
archive(restored);
}
return 0;
}
3. nlohmann/json (JSON for Modern C++)
Самая популярная библиотека для работы с JSON в C++. Хотя изначально не предназначена для сериализации объектов, её можно легко адаптировать с помощью пользовательских преобразователей (adapter pattern).
- Преимущества: простой и красивый синтаксис, отличная документация, header-only, интеграция с любыми типами.
- Недостатки: работает только с JSON, не поддерживает бинарные форматы, для сложных графов объектов требуется ручное описание.
#include <nlohmann/json.hpp>
#include <fstream>
using json = nlohmann::json;
struct Point {
double x, y;
};
void to_json(json& j, const Point& p) {
j = json{{"x", p.x}, {"y", p.y}};
}
void from_json(const json& j, Point& p) {
p.x = j.at("x").get<double>();
p.y = j.at("y").get<double>();
}
int main() {
Point pt{3.14, 2.71};
json j = pt;
std::ofstream("point.json") << j.dump(4);
// Десериализация
std::ifstream ifs("point.json");
json j2 = json::parse(ifs);
Point restored = j2.get<Point>();
return 0;
}