Главная  /  Правка версии 2  /  Правка версии 3  /   /  Область пользователей

Отличия "Сериализация" вер. 2 сравн. вер. 3

Содержимое:

<!--toc-->
## Введение
Часто требуется сохранить некоторые объекты C++ в хранилище данных какого-то типа, вроде пользовательской сессии или кэша и извлечь их обратно.
Это нетривиальная задача для C++ - [нерефлексивного](http://ru.wikipedia.org/wiki/%D0%9E%D1%82%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29) языка. Поэтому CppCMS обеспечивает простую библиотеку сериализации, которая помогает нам выполнять такие задачи.
## Инструменты Сериализации CppCMS
### Подготовка Объектов
Предположим, у нас есть класс `person`, содержащий некоторую информацию и список его потомков - классы `child`.
Человек:
struct person {
std::string name;
std::string family;
std::string occupation;
std::string martial_state;
double salary;
physical parameters;
std::list<child> children;
std::vector<std::string> friends;
};
Потомок:
struct child {
std::string name;
physical parameters;
}
Физические данные о них:
struct physical {
int age;
double height;
};
Теперь, чтобы сериализовать наш объект, мы можем наследовать его от класса `cppcms::serializable`. Добавьте заголовочный файл `<cppcms/serialization.h>` и обновите объект так, чтобы:
struct child {
...
};
struct person {
...
};
стало
struct child : public cppcms::serializable {
...
};
struct person : public cppcms::serializable {
...
};
_Примечание:_ Так как объект "physical" - [POD](http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D1%81%D1%82%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85), мы можем обработать его лучшим образом.
Теперь добавим двум классам выше новый метод, описывающий как их сериализовать:
Потомок:
void serialize(cppcms::archive &a)
{
a & name & cppcms::as_pod(parameters);
}
Метод получает в качестве параметра `cppcms::archive` - объект, способный сохранить/восстановить нужные данные и мы отмечаем каждый элемент: `name` и `parameters`.
_Примечание:_ поскольку мы знаем, что `parameters` - POD-объект, мы используем специальный маркер, описывающий как его скопировать.
Далее делаем то же самое для класса `person`:
void serialize(cppcms::archive &a)
{
a & name & family & occupation & martial_state
& salary & cppcms::as_pod(parameters) & children & friends;
}
**Замечание:**
Объект `archive` знает, как обращаться со стандартными C++-контейнерами типа `std::vector` или `std::string`. Он знает, как сохранить примитивные типы вроде `double` в виде простых двоичных данных.
Потому, например, т.к. `children` это `std::list<child>` и `child` наследуется от `cppcms::serializable`, он знает как автоматически справиться с этой ситуацией.
Если Вы используете собственные или нестандартные контейнеры, возможно потребуется специализация класса: [`cppcms::archive_traits`](/cppcms_ref/1.0.2/structcppcms_1_1archive__traits.html) для Вашего конкретного класса.
### Сохранение и Восстановление Объектов
Предположим, что `std::string buffer` - наш контейнер данных.
Таким образом, мы можем сохранить данные в буфер с помощью следующих действий:
person john;
... // проинициализировать его данные
cppcms::archive a;
john.save(a); // сохранить их в архив
buffer = a.str(); // взять буфер
Мы можем загрузить их так:
person john;
cppcms::archive a;
a.str(buffer);
john.load(a);
Это простейший способ сохранения и загрузки данных, но мы рекомендуем использовать чуть более сложное API которое, как увидим позже, даст нам больше возможностей:
Save:
person john;
... // setup its data
... // проинициализировать его данные
cppcms::serialization_traits<person>::save(john,buffer);
Load:
person john;
cppcms::serialization_traits<person>::load(buffer,john);
### Использование с Кэшем и Сессиями
Теперь давайте посмотрим, как мы можем использовать инструменты сериализации CppCMS с интерфейсами Кэша и Сессий:
Можем легко закэшировать объекты `person` следующим образом:
person john;
if(!cache().fetch_data("john",john)) {
init_person(john);
cache().store_data("john",john);
}
Это бы позволило, например, снизить число сложных запросов к базе данных для некоторых общих данных, которые не обновлялись.
Можем сохранить объекты с помощью сессий:
person me;
if(session().is_set("me")) {
session().fetch_data("me",me);
me.salary += 1;
session().store_data("me",me);
}
## Использование Стороннего API Сериализации
### Принцип
CppCMS API - простое, быстрое и мощное, но сильно зависит от платформы - оно не позволяет передать один и тот же объект между хостами с различной архитектурой или порядком следования байт, не поддерживает версионность и прочее.
Поэтому, в некоторых случаях может потребоваться использование с CppCMS сторонних API.
Это довольно просто, все что нужно сделать - предоставить специализацию класса `serialization_traits` - вот в чем и была причина, по которой мы рекомендовали использовать класс `serialization_traits`, вместо прямого использования `cppcms::archive`.
### Boost.Serialization
Давайте посмотрим, как использовать, например, Boost.Serialization с CppCMS.
Это наш простейший класс, поддерживающий Boost.Serialization:
struct person {
std::string name;
std::string family;
template<typename Archive>
void serialize(Archive &a,unsigned /*version*/)
{
a & name & family;
}
};
Давайте определим две небольшие вспомогательные функции для сохранения и загрузки объекта в строку:
template<typename T>
void load_from_boost(std::string const &src,T &obj)
{
std::stringbuf ss(src);
{
boost::archive::binary_iarchive oa(ss);
oa >> obj;
}
}
template<typename T>
void save_with_boost(T const &obj,std::string &tgt)
{
std::stringbuf ss;
{
boost::archive::binary_oarchive oa(ss);
oa << obj;
}
tgt=ss.str();
}
Теперь все, что нам нужно, это специализация нашего `serialization_traits` для корректной обработки `person`:
namespace cppcms {
template<>
struct serialization_traits<person> {
static void save(person const &obj,std::string &tgt)
{
save_with_boost(obj,tgt);
}
static void load(std::string const &src,person &obj)
{
load_from_boost(src,obj);
}
};
}
В дальнейшем можно будет свободно сохранять и загружать объект с помощью CppCMS интерфейса сессии или кэша:
person john;
if(!cache().fetch_data("john",john)) {
init_person(john);
cache().store_data("john",john);
}

Проект

CppCMS является основой веб-разработки для выполнения ресурсоемких приложений.

Размещение

SourceForge.net Logo

Поддержать проект

CppCMS needs You


Навигация

Главная страница


Валидация CSS | Валидация XHTML 1.0