Сериализация данных: JSON, XML, Protocol Buffers
Что такое сериализация, форматы, сравнение, производительность, использование в API.
Введение
Каждый раз, когда данные передаются между процессами, сохраняются на диск или уходят по сети, они проходят через сериализацию — преобразование из внутренних структур программы в линейную последовательность байтов. Без сериализации невозможен ни один API, ни одна база данных, ни один кэш. JSON, XML, Protocol Buffers, MessagePack, Avro — это всё форматы сериализации, каждый со своими компромиссами между читаемостью, размером, скоростью и типизированностью. В этой статье разберём, что такое сериализация, какие бывают форматы, в чём их отличия и как выбрать подходящий для конкретной задачи.
Что такое сериализация
Сериализация (serialization) — это процесс перевода структуры данных из оперативного представления (объекты в памяти, деревья, графы) в линейный формат, пригодный для хранения или передачи. Обратный процесс называется десериализацией (deserialization, или unmarshalling): из линейного формата восстанавливается исходная структура. Сериализация — фундамент распределённых систем: без неё микросервисы не смогли бы общаться, базы данных — хранить сложные объекты, а веб-страницы — получать данные от сервера.
Хороший формат сериализации должен удовлетворять нескольким требованиям: быть компактным (экономить трафик и место), быстрым для кодирования и декодирования, поддерживать типы данных (числа, строки, булевы, массивы, объекты), быть переносимым между языками программирования и платформами, поддерживать эволюцию схемы (добавление и удаление полей без нарушения совместимости). Идеального формата не существует — каждый компромисс в одном месте отнимает в другом.
Классификация форматов
Форматы сериализации делятся на две большие группы: текстовые и бинарные. Текстовые (JSON, XML, YAML, TOML) читаемы человеком, легко отлаживаются, но занимают больше места и медленнее парсятся. Бинарные (Protocol Buffers, MessagePack, Avro, CBOR, BSON) компактны и быстры, но не читаются без специальных инструментов. Внутри каждой группы есть деление на самописные (self-describing — JSON, XML) и требующие внешней схемы (Protocol Buffers, Avro).
| Формат | Тип | Схема | Читаемость | Размер | Скорость |
|---|---|---|---|---|---|
| JSON | Текстовый | Самоописывающий | Высокая | Средний | Средняя |
| XML | Текстовый | Самоописывающий | Средняя | Большой | Низкая |
| YAML | Текстовый | Самоописывающий | Очень высокая | Маленький | Низкая |
| Protocol Buffers | Бинарный | Внешняя (.proto) | Нет | Маленький | Высокая |
| MessagePack | Бинарный | Самоописывающий | Нет | Маленький | Высокая |
| Avro | Бинарный | Внешняя (JSON-схема) | Нет | Очень маленький | Высокая |
JSON: король веба
JSON (JavaScript Object Notation) — самый популярный формат сериализации в вебе. Он появился в 2001 году как упрощённая альтернатива XML, и к 2010-м фактически вытеснил XML из REST API. JSON поддерживает шесть типов данных: строка, число, булево, null, массив, объект. Этого достаточно для 95% задач, и именно эта простота сделала JSON универсальным стандартом.
Главные плюсы JSON: читаемость (текстовый формат), нативная поддержка в JavaScript (через JSON.parse и JSON.stringify), универсальность (есть парсеры во всех языках), компактность по сравнению с XML. Минусы: нет типов (числа без различения int/float, нет даты), нет комментариев (стандарт запрещает, хотя есть JSONC/JSON5), большой размер для числовых данных (числа кодируются как текст), медленный парсинг для больших объёмов.
// Пример JSON
{
"user": {
"id": 42,
"name": "Анна Иванова",
"email": "anna@example.com",
"roles": ["admin", "editor"],
"active": true,
"createdAt": "2025-04-09T10:30:00Z"
}
}
// JavaScript: нативная сериализация
const data = { user: { id: 42, name: "Анна" } };
const json = JSON.stringify(data, null, 2); // beautify
const parsed = JSON.parse(json); // десериализацияДля сложных задач поверх JSON строятся расширения: JSON Schema (описание и валидация структуры), JSON-LD (связанные данные), JSON API (стандарт для API), JSON5 (с комментариями и relaxed-синтаксисом), JSONC (с comments от Microsoft). Если вам нужно работать с JSON, используйте наш JSON форматтер или конвертеры JSON в XML иJSON в YAML.
XML: классика enterprise
XML (eXtensible Markup Language) — текстовый формат с тегами, похожий на HTML, но с произвольной структурой. Появился в 1996 году, был стандартом для SOAP-сервисов, конфигов, документооборота. Сегодня XML используется реже, но всё ещё встречается в enterprise-системах: банковские системы, бухгалтерия (1С), офисные документы (DOCX, XLSX — это ZIP с XML внутри), SVG, RSS, Sitemap.xml.
Плюсы XML: расширяемость (можно создавать любые теги и атрибуты), мощная экосистема (XPath, XSLT, XSD-схемы, пространства имён), поддержка типов через XSD, возможность валидации. Минусы: избыточность (закрывающие теги, атрибуты), большой размер, медленный парсинг, сложность для чтения больших документов. XML оправдан в enterprise и документообороте, но для новых проектов обычно выбирают JSON.
<!-- Тот же объект в XML -->
<user>
<id>42</id>
<name>Анна Иванова</name>
<email>anna@example.com</email>
<roles>
<role>admin</role>
<role>editor</role>
</roles>
<active>true</active>
<createdAt>2025-04-09T10:30:00Z</createdAt>
</user>
<!-- Тот же объект в JSON занял бы на 30–40% меньше места -->Protocol Buffers: бинарная эффективность
Protocol Buffers (protobuf) — бинарный формат от Google, разработанный в 2001 году для внутренних нужд и открытый в 2008. Использует внешнее описание схемы в .proto-файлах, из которых генерируется код для разных языков. Protobuf в 3–10 раз компактнее JSON и в 10–100 раз быстрее парсится. Используется в gRPC, внутренних API Google, многих микросервисных архитектурах.
// Схема в .proto-файле
syntax = "proto3";
message User {
int32 id = 1;
string name = 2;
string email = 3;
repeated string roles = 4;
bool active = 5;
int64 createdAt = 6; // timestamp вместо строки
}
// Сериализация (Python)
import user_pb2
user = user_pb2.User(id=42, name="Анна", email="anna@example.com")
data = user.SerializeToString() # ~30 байт вместо ~150 в JSON
# Десериализация
parsed = user_pb2.User()
parsed.ParseFromString(data)Плюсы protobuf: компактность, скорость, строгая типизация, поддержка эволюции схемы (через optional/repeated поля и номера), богатая ecosystem (gRPC, Buf, документация схем). Минусы: не читается без схемы, нужен кодогенератор для каждого языка, сложнее дебажить (нужны инструменты), бинарный формат не подходит для прямого просмотра в браузере.
MessagePack и Avro: альтернативы
MessagePack — бинарный формат, по структуре повторяющий JSON, но в бинарной форме. Самоописывающий, не требует внешней схемы. По размеру в 2–3 раза компактнее JSON, парсится быстрее. Удобен, когда нужно уменьшить payload без усложнения инфраструктуры. Используется в Redis, Memcached, некоторых realtime-протоколах.
Avro — бинарный формат из Apache Hadoop экосистемы. Использует JSON-схему для описания данных, но сам сериализованный формат не содержит имён полей (только значения) — поэтому ещё компактнее protobuf. Схема передаётся вместе с данными или согласуется заранее. Avro оптимален для потоковой обработки больших объёмов данных: Kafka, Hadoop, хранилища данных.
Сравнение производительности
Сравним размеры и скорости для типичного объекта (User с 6 полями, как в примерах выше). Цифры приблизительные, зависят от реализации и данных, но порядок величин показателен.
| Формат | Размер (байты) | Сериализация (мкс) | Десериализация (мкс) |
|---|---|---|---|
| JSON | 152 | 12 | 35 |
| XML | 238 | 45 | 120 |
| YAML | 118 | 180 | 450 |
| MessagePack | 62 | 4 | 8 |
| Protocol Buffers | 34 | 2 | 3 |
| Avro | 28 | 3 | 5 |
Разница колоссальная: protobuf в 4,5 раза компактнее JSON и в 10 раз быстрее. Для высоконагруженных систем с миллионами запросов в секунду это критично. Однако для типичного CRUD-приложения с тысячами запросов разница незаметна — JSON справляется легко, и его читаемость перевешивает преимущество в скорости.
Когда что выбирать
JSON
- Публичные REST API — читаемость важнее компактности.
- Конфиги и документы для людей — package.json, tsconfig.json.
- Browser-server communication — нативная поддержка в JS.
- Бэкенды с малой и средней нагрузкой — до 10k RPS.
- Прототипирование и разработка — легко дебажить.
XML
- Интеграция с legacy-системами — SOAP, банковские сервисы.
- Документооборот — счета, акты в 1С.
- Сложные документы с проверкой — XSD-схемы, валидация.
- SVG, RSS, Sitemap — форматы, где XML стандартизирован.
Protocol Buffers
- Внутренние API микросервисов — gRPC.
- Высоконагруженные системы — десятки тысяч RPS.
- Стриминг данных между сервисами — компактность и скорость.
- Межъязыковое взаимодействие — кодогенерация для всех языков.
Avro
- Хранение больших объёмов — Parquet, ORC под капотом.
- Стриминг в Kafka — schema registry, эволюция схем.
- Big Data пайплайны — Hadoop, Spark, Flink.
Эволюция схемы
Реальные системы меняются: добавляются поля, удаляются, переименовываются. Формат должен поддерживать эволюцию без нарушения совместимости. JSON справляется легко — неизвестные поля просто игнорируются при десериализации, отсутствующие становятся undefined. XML — через optional-атрибуты и пространства имён. Protobuf — через номера полей (можно удалять, нельзя переиспользовать номера), reserved fields, optional-поля. Avro — через схему с правилами совместимости (backward, forward, full).
Для публичных API с внешними клиентами эволюция критична. JSON + JSON Schema с optional-полями и версионированием — простой и эффективный подход. Для внутренних API с жёсткой типизацией protobuf с правилами эволюции — лучший выбор.
Безопасность при десериализации
Десериализация — известная категория уязвимостей. Если десериализовать недоверенные данные без проверки, можно получить удалённое выполнение кода (RCE). Классический пример — Java-сериализация с полиморфными объектами: атакующий подсунул сериализованный объект с вредоносным кодом, который выполнился при десериализации. Аналогичные уязвимости были в Python pickle, Ruby Marshal, PHP unserialize.
JSON и XML относительно безопасны — парсеры не выполняют код. Но есть нюансы: XXE (XML External Entity) — атака через XML-сущности, позволяющая читать файлы сервера. JSON Hijacking — атака на старые браузеры через JSONP. В современных парсерах XXE отключён по умолчанию, но проверяйте конфигурацию. Для protobuf и Avro безопасность выше — данные жёстко типизированы схемой.
Заключение
Сериализация — невидимая, но критическая часть любой системы. JSON — оптимальный выбор для большинства веб-API благодаря читаемости, простоте и универсальности. XML оправдан в enterprise и документообороте. Protocol Buffers и Avro — для высоконагруженных систем и big data, где важна компактность и скорость. Выбор формата — это компромисс между читаемостью, размером, скоростью и типизацией. Для новых проектов начинайте с JSON, и переходите на бинарные форматы только когда упрётесь в производительность. Подробнее о JSON — в нашей статье «JSON форматтер: зачем нужен и как использовать», о сравнении JSON и XML — в материале «JSON vs XML».
Попробуйте эти инструменты
Похожие статьи
Client-side vs Server-side: где обрабатывать файлы
Сравнение обработки файлов в браузере vs на сервере: приватность, скорость, ограничения, безопасность.
Почему браузерные инструменты лучше облачных
Преимущества client-side обработки: приватность, нет загрузки, нет регистрации, скорость, бесплатно.
Конвертация файлов: лучшие практики
Правила конвертации: сохранение качества, выбор формата, batch обработка, автоматизация.
Оптимизация веб-производительности: изображения
Lazy loading, responsive images, современные форматы (WebP, AVIF), CDN, сжатие, влияние на SEO.