Сериализация данных
Сериализация данных — это процесс преобразования структуры данных (объектов, массивов, записей) в линейную последовательность байтов или строку, пригодную для хранения в файле, передачи по сети или записи в базу данных. Обратный процесс, восстанавливающий исходную структуру, называется десериализацией. Сериализация является фундаментальной концепцией в информатике, обеспечивающей сохранение состояния объектов между сеансами работы программы, обмен данными между различными системами и компонентами, а также взаимодействие распределённых вычислений.
История
Потребность в сериализации возникла с появлением первых компьютерных сетей и многопользовательских систем. В 1960-х годах для передачи данных между мейнфреймами использовались простые текстовые форматы, такие как фиксированные записи. С развитием объектно-ориентированного программирования в 1980-х годах возникла необходимость сохранять не только данные, но и структуру объектов, включая их взаимосвязи.
Одним из первых стандартизированных механизмов сериализации стал формат External Data Representation (XDR), разработанный компанией Sun Microsystems в 1987 году для использования в протоколе удалённого вызова процедур (RPC). В 1990-х годах с распространением языка Java компания Sun ввела встроенную сериализацию объектов (Java Object Serialization), которая автоматически преобразовывала графы объектов в поток байтов. В языке C++ сериализация не была встроенной, но широко использовались библиотеки, такие как Boost.Serialization.
В 2000-х годах с ростом популярности веб-сервисов и микросервисной архитектуры возник спрос на лёгкие, человеко-читаемые форматы. В 2001 году был опубликован стандарт JSON (JavaScript Object Notation), который стал де-факто стандартом для обмена данными в веб-приложениях. В 2004 году появился XML, который, несмотря на свою избыточность, остаётся популярным в корпоративных системах. В 2010-х годах для высокопроизводительных систем были разработаны бинарные форматы, такие как Protocol Buffers (Google, 2008), Apache Avro (2010) и FlatBuffers (Google, 2014).
Классификация
Сериализация данных может быть классифицирована по нескольким признакам.
По типу представления
- Текстовые форматы: данные преобразуются в строку, читаемую человеком. Примеры: JSON, XML, YAML, CSV. Преимущества — удобство отладки и совместимость с различными системами. Недостатки — больший объём данных по сравнению с бинарными форматами и более низкая скорость обработки.
- Бинарные форматы: данные преобразуются в последовательность байтов, не предназначенную для непосредственного чтения человеком. Примеры: Protocol Buffers, Avro, MessagePack, Java Serialization, Python pickle. Преимущества — высокая скорость сериализации/десериализации и компактность. Недостатки — сложность отладки и необходимость точного согласования схемы данных.
По способу описания структуры
- Самодокументируемые форматы: структура данных (схема) встраивается в сериализованный поток вместе с данными. Примеры: XML, JSON (схема может быть описана отдельно, но часто не используется), Avro (схема хранится вместе с данными или в заголовке файла).
- Форматы с внешней схемой: структура данных описывается отдельно, а сериализованный поток содержит только значения. Примеры: Protocol Buffers (схема описана в
.proto-файле), Thrift (схема в.thrift-файле). Это позволяет уменьшить размер данных, но требует синхронизации схемы между отправителем и получателем.
По языковой привязке
- Языкозависимые: механизмы, встроенные в конкретный язык программирования. Примеры: Java Object Serialization, Python pickle, Ruby Marshal. Они просты в использовании, но создают данные, несовместимые с другими языками.
- Языконезависимые: форматы, которые могут быть прочитаны и записаны программами на разных языках. Примеры: JSON, XML, Protocol Buffers, Avro. Они обеспечивают интероперабельность, но требуют дополнительных библиотек.
Основные форматы
JSON
JSON (JavaScript Object Notation) — текстовый формат, основанный на синтаксисе литералов объектов JavaScript. Поддерживает четыре примитивных типа (строка, число, логическое значение, null) и два составных (объект — неупорядоченный набор пар «ключ-значение», массив — упорядоченный список). JSON является стандартом ECMA-404 и RFC 8259. Широко используется в REST API, конфигурационных файлах, веб-приложениях. Недостатки: отсутствие поддержки типов данных, таких как дата/время или двоичные данные, и ограниченная поддержка циклических ссылок.
XML
XML (eXtensible Markup Language) — текстовый формат, основанный на тегах. Поддерживает произвольные структуры, атрибуты, пространства имён и схемы (DTD, XSD). XML используется в веб-сервисах (SOAP), конфигурационных файлах (например, в Android-приложениях), документах (SVG, XHTML). Недостатки: избыточность, сложность парсинга и большой объём данных.
Protocol Buffers
Protocol Buffers (protobuf) — бинарный формат, разработанный Google. Данные описываются в .proto-файлах с помощью специального языка описания интерфейсов. Protobuf обеспечивает высокую скорость сериализации и компактность (размер данных в несколько раз меньше, чем JSON). Используется в системах с высокой нагрузкой, таких как Google Search, YouTube, а также в микросервисной архитектуре (gRPC). Недостатки: необходимость компиляции схемы и сложность отладки.
Avro
Apache Avro — бинарный формат, разработанный в рамках проекта Apache Hadoop. Ключевая особенность — схема данных хранится вместе с данными (в заголовке файла или в потоке). Avro поддерживает эволюцию схемы (добавление/удаление полей без нарушения совместимости). Широко используется в системах обработки больших данных (Apache Kafka, Apache Spark). Недостатки: меньшая скорость по сравнению с protobuf.
YAML
YAML (YAML Ain’t Markup Language) — текстовый формат, ориентированный на удобство чтения человеком. Использует отступы для обозначения вложенности. Поддерживает сложные структуры, такие как ссылки и якоря. YAML часто используется в конфигурационных файлах (Docker Compose, Kubernetes, Ansible). Недостатки: сложность парсинга и потенциальные проблемы с безопасностью (возможность выполнения произвольного кода в некоторых реализациях).
Применение
Сериализация данных используется в широком спектре задач:
- Хранение состояния: сохранение состояния игры, настроек пользователя, кэша данных. Например, игровые движки (Unity, Unreal Engine) используют сериализацию для сохранения прогресса.
- Сетевое взаимодействие: передача данных между клиентом и сервером, между микросервисами. Например, REST API использует JSON, gRPC — Protocol Buffers.
- Удалённый вызов процедур (RPC): сериализация аргументов и возвращаемых значений при вызове методов удалённого объекта. Примеры: Java RMI, CORBA, gRPC.
- Обмен данными между системами: интеграция разнородных систем, обмен данными в формате XML или JSON. Например, в банковской сфере используется ISO 20022 (XML).
- Хранение в базах данных: сериализация сложных объектов в столбцы типа JSON или BLOB. Например, PostgreSQL поддерживает тип JSONB, MongoDB хранит документы в формате BSON.
- Кэширование: сериализация объектов для хранения в кэш-системах, таких как Redis или Memcached.
Проблемы и ограничения
- Циклические ссылки: при сериализации графа объектов, содержащего циклические ссылки, может возникнуть бесконечный цикл. Для решения этой проблемы используются механизмы отслеживания уже сериализованных объектов (например, в Java Serialization) или специальные форматы (например, JSON не поддерживает циклические ссылки, поэтому их необходимо обрабатывать вручную).
- Безопасность: десериализация данных из ненадёжного источника может привести к выполнению произвольного кода (например, уязвимости в Python pickle или Java Serialization). Рекомендуется использовать безопасные форматы (JSON, Protocol Buffers) и проверять источник данных.
- Версионирование: при изменении структуры данных (добавление/удаление полей) необходимо обеспечить обратную совместимость. Для этого используются механизмы эволюции схемы (например, в Avro и Protocol Buffers) или версионирование API.
- Производительность: текстовые форматы (JSON, XML) медленнее бинарных (Protocol Buffers, Avro) и занимают больше места. Для высоконагруженных систем рекомендуется использовать бинарные форматы.
Интересные факты
- Формат JSON был впервые описан Дугласом Крокфордом в 2001 году. Он был создан как подмножество JavaScript, но быстро стал независимым стандартом.
- Protocol Buffers используются в Google для хранения данных в Bigtable и для обмена данными между сервисами. В 2008 году Google опубликовал спецификацию и реализацию для нескольких языков.
- Apache Avro был разработан для решения проблем совместимости схем в Hadoop. Его название происходит от названия британской авиастроительной компании Avro.
- В языке C# сериализация объектов поддерживается через атрибуты
[Serializable]и[DataContract]. В .NET Core также доступен System.Text.Json для работы с JSON. - В языке Rust сериализация и десериализация реализуются с помощью крейта
serde, который поддерживает множество форматов (JSON, YAML, BSON, MessagePack и другие).
Источники
- ECMA-404: The JSON Data Interchange Standard
- RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format
- Google Developers: Protocol Buffers Documentation
- Apache Avro Specification
- YAML Specification v1.2
- «Сериализация данных» в курсе «Основы программирования» (Stepik)
- «Сериализация и десериализация» в документации Microsoft .NET
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →