cloud-castle / serialize
Безопасная сериализация для PHP 8.1+: PHP/JSON/igbinary из одного API, HMAC-подпись, белый список классов и лимит размера при десериализации, маппинг объект↔массив и экспорт в PHP-код. Нулевые внешние зависимости.
Requires
- php: >=8.1
- ext-json: *
Requires (Dev)
- brick/varexporter: ^0.6
- cuyz/valinor: ^1.8
- deptrac/deptrac: ^3.0 || ^4.0
- ergebnis/composer-normalize: ^2.45
- friendsofphp/php-cs-fixer: ^3.75
- icanhazstring/composer-unused: ^0.9
- infection/infection: ^0.29 || ^0.33
- jms/serializer: ^3.30
- laravel/serializable-closure: ^1.3 || ^2.0
- php-parallel-lint/php-parallel-lint: ^1.4
- phpmd/phpmd: ^2.15
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^1.12 || ^2.1
- phpstan/phpstan-deprecation-rules: ^1.2 || ^2.0
- phpstan/phpstan-phpunit: ^1.4 || ^2.0
- phpstan/phpstan-strict-rules: ^1.6 || ^2.0
- phpunit/phpunit: ^10.5 || ^11.5
- psalm/plugin-phpunit: ^0.19 || ^0.20
- rector/rector: ^1.2 || ^2.0
- roave/security-advisories: dev-latest
- squizlabs/php_codesniffer: ^3.12 || ^4.0
- symfony/serializer: ^6.4 || ^7.0
- symfony/var-exporter: ^6.4 || ^7.0
- symfony/yaml: ^6.4 || ^7.0
- vimeo/psalm: ^6.0
- webmozart/assert: ^1.11
This package is auto-updated.
Last update: 2026-07-29 09:12:05 UTC
README
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano
CloudCastle Serialize
Один API для восьми форматов сериализации PHP с безопасностью по умолчанию: объекты не восстанавливаются без явного разрешения, а нагрузку можно подписать, зашифровать, сжать и ограничить сроком жизни. Нулевые обязательные зависимости.
Установка
composer require cloud-castle/serialize
Требуется PHP 8.1+. Форматы igbinary и MessagePack используют одноимённые расширения; всё остальное работает на стандартной сборке PHP.
Быстрый старт
<?php
use CloudCastle\Serialize\Context;
use CloudCastle\Serialize\Serializer;
// PHP-формат: объекты запрещены по умолчанию (защита от gadget-chain).
$payload = Serializer::php([Order::class])->serialize($order);
$order = Serializer::php([Order::class])->unserialize($payload);
// Восемь форматов за одним интерфейсом.
$json = Serializer::json()->serialize($data);
$xml = Serializer::xml()->serialize($data); // типы не теряются
$csv = Serializer::csv()->serialize($rows);
$yaml = Serializer::yaml()->serialize($config);
$ndjson = Serializer::ndjson()->serialize($collection); // построчный поток
// Защита нагрузки собирается композицией: подпись, TTL, сжатие, шифрование.
$token = Serializer::signed($key, Serializer::expiring(3600, Serializer::json()));
$sealed = $token->seal(['user' => 42]);
$data = $token->unseal($sealed); // подделка и просрочка отклоняются до разбора
// Анонимные функции и объекты анонимных классов — на любой глубине структуры.
$codec = Serializer::dynamic($key);
$payload = $codec->serialize([
'handler' => static fn (int $x): int => $x * 2,
'policy' => new class { public int $limit = 10; },
]);
$data = $codec->unserialize($payload);
$data['handler'](21); // 42
$data['policy']->limit; // 10
// Маппинг объектов: группы, версии схемы, маскирование персональных данных.
$public = Serializer::mapper()->toArray($order, Context::create()->withGroups(['public']));
$safe = Serializer::mapper()->toArray($order, Context::forLogging()); // ПД замаскированы
$order = Serializer::mapper()->fromArray(Order::class, $public);
Возможности
- Восемь форматов за единым интерфейсом: PHP, JSON, XML, CSV, YAML, NDJSON, igbinary, MessagePack — плюс экспорт в исполняемый PHP-код.
- Безопасность по умолчанию: объекты не восстанавливаются без белого списка, размер и глубина нагрузки ограничены, XML отклоняет DTD, распаковка архива лимитирована.
- Защита нагрузки композицией: HMAC-подпись с ротацией ключей, шифрование XSalsa20-Poly1305, срок жизни, прозрачное сжатие — в любых сочетаниях.
- Маппинг объект ↔ массив на атрибутах: группы, версии схемы, стратегии именования, типизированные коллекции, полиморфизм, маскирование ПД для логов.
- Потоковая обработка коллекций: запись и чтение по одному элементу — пиковая память не зависит от размера набора.
- Анонимные функции и объекты анонимных классов переносятся сквозь любую структуру — с обязательной подписью кода, поскольку нагрузка исполняемая.
- Ноль обязательных зависимостей — ни одной транзитивной уязвимости.
Описание каждой возможности с примерами, диаграммами и сравнением с аналогами — в wiki.
Сравнение с аналогами
Все таблицы ниже сгенерированы автоматически из честных сравнительных прогонов (benchmarks/compare.php): каждое решение выполняет одинаковую работу на PHP 8.1.34 без Xdebug.
1. Функциональность
| Возможность | CloudCastle | symfony/serializer | jms/serializer | valinor | var-exporter | varexporter | serializable-closure | symfony/yaml | 🏆 Победитель |
|---|---|---|---|---|---|---|---|---|---|
| Формат PHP (native serialize) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Формат JSON | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle, symfony/serializer … |
| Формат XML | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle, symfony/serializer … |
| Формат CSV | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle, symfony/serializer |
| Формат YAML | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | CloudCastle, symfony/serializer … |
| Формат NDJSON (построчный поток) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Формат igbinary | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Формат MessagePack | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Экспорт в исполняемый PHP-код | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | CloudCastle, var-exporter … |
| Маппинг объект ↔ массив | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | CloudCastle, symfony/serializer … |
| Типизированные коллекции без docblock-парсинга | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | CloudCastle, jms/serializer … |
| Полиморфизм по карте дискриминатора | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | CloudCastle, symfony/serializer … |
| Группы сериализации | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle, symfony/serializer … |
| Версионирование схемы (since/until) | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle, jms/serializer |
| Стратегии именования (snake/kebab/pascal) | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle, symfony/serializer … |
| Маскирование персональных данных для логов | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Белый список классов при десериализации | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Лимит размера нагрузки | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Лимит вложенности графа объектов | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle, symfony/serializer |
| HMAC-подпись нагрузки | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | CloudCastle, serializable-closure |
| Ротация ключей подписи без простоя | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Шифрование нагрузки (XSalsa20-Poly1305) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Срок жизни нагрузки (TTL) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Прозрачное сжатие нагрузки | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Сериализация замыканий | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | CloudCastle, serializable-closure |
| Анонимные функции внутри произвольных структур | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Сериализация объектов анонимных классов | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Потоковая запись и чтение коллекций | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Обнаружение циклических ссылок | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle, symfony/serializer |
| Ноль обязательных зависимостей | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Всего | 30 | 10 | 9 | 3 | 1 | 1 | 2 | 1 | 🏆 CloudCastle |
2. Безопасность и корректность
| Свойство | CloudCastle | symfony/serializer | jms/serializer | valinor | var-exporter | varexporter | serializable-closure | symfony/yaml | 🏆 Победитель |
|---|---|---|---|---|---|---|---|---|---|
| Объекты запрещены при десериализации по умолчанию | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | CloudCastle, symfony/serializer … |
| Белый список классов вместо «доверяем нагрузке» | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | CloudCastle, symfony/serializer … |
| Лимит размера нагрузки до разбора | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Лимит вложенности графа | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle, symfony/serializer |
| HMAC-подпись со сверкой за константное время | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Ротация ключей подписи | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Аутентифицированное шифрование нагрузки | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Ограничение срока действия нагрузки | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Запрет DTD при разборе XML (анти-XXE) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Лимит распаковки архива (анти-zip-бомба) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Маскирование персональных данных в логах | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Обязательная подпись при сериализации кода | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | CloudCastle, serializable-closure |
| Контрактные исключения вместо предупреждений | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | CloudCastle, symfony/serializer … |
| Ноль транзитивных зависимостей в рантайме | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | CloudCastle |
| Всего | 14 | 4 | 3 | 3 | 1 | 1 | 1 | 2 | 🏆 CloudCastle |
3. Качество кода
| Метрика | CloudCastle | symfony/serializer | jms/serializer | valinor | var-exporter | varexporter | serializable-closure | symfony/yaml | 🏆 Победитель |
|---|---|---|---|---|---|---|---|---|---|
| Обязательных зависимостей в рантайме | 0 | 2 | 4 | 2 | 1 | 1 | 0 | 2 | 🏆 CloudCastle |
| Файлов со строгой типизацией, % | 100 | 0 | 100 | 98.4 | 0 | 100 | 0 | 0 | 🏆 CloudCastle |
| Строк кода | 5781 | 11933 | 13999 | 23297 | 2981 | 1238 | 2751 | 3328 | без победителя |
| Строк кода на одну возможность | 193 | 1193 | 1555 | 7766 | 2981 | 1238 | 1376 | 3328 | 🏆 CloudCastle |
4. Производительность
20 000 итераций, минимум из 3 прогонов, мс.
| Решение | CloudCastle | symfony/serializer | jms/serializer | valinor | var-exporter | varexporter | serializable-closure | symfony/yaml | serialize¹ | json¹ | igbinary¹ | msgpack¹ | var_export¹ | 🏆 Победитель |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Round-trip вложенной структуры | 56,9 | 83,9 | 471,5 | — | — | — | — | — | 47,3 | 73,3 | 33,6 | 45 | — | 🏆 CloudCastle |
| Маппинг объекта в массив и обратно | 287,1 | 993,3 | — | 1 124,3 | — | — | — | — | — | — | — | — | — | 🏆 CloudCastle |
| Экспорт значения в исполняемый PHP-код | 165,7 | — | — | — | 421,4 | 538,2 | — | — | — | — | — | — | 71,2 | 🏆 CloudCastle |
| Round-trip конфигурации в YAML | 968,1 | — | — | — | — | — | — | 5 014,4 | — | — | — | — | — | 🏆 CloudCastle |
| Round-trip замыкания | 2 939,3 | — | — | — | — | — | 1 208,1 | — | — | — | — | — | — | 🏆 serializable-closure |
5. Потребление памяти
пик памяти самой библиотеки на 20 000 итераций (изолированный процесс, вычет базовой линии), KB.
| Решение | CloudCastle | symfony/serializer | jms/serializer | valinor | var-exporter | varexporter | serializable-closure | symfony/yaml | serialize¹ | json¹ | igbinary¹ | msgpack¹ | var_export¹ | 🏆 Победитель |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Round-trip вложенной структуры | 47 | 29 | 1 051 | — | — | — | — | — | 1 | 1 | 1 | 1 | — | 🏆 symfony/serializer |
| Маппинг объекта в массив и обратно | 187 | 1 026 | — | 1 283 | — | — | — | — | — | — | — | — | — | 🏆 CloudCastle |
| Экспорт значения в исполняемый PHP-код | 44 | — | — | — | 75 | 1 235 | — | — | — | — | — | — | 1 | 🏆 CloudCastle |
| Round-trip конфигурации в YAML | 87 | — | — | — | — | — | — | 380 | — | — | — | — | — | 🏆 CloudCastle |
| Round-trip замыкания | 5 054 | — | — | — | — | — | 5 330 | — | — | — | — | — | — | 🏆 CloudCastle |
¹ Базовый уровень — нативные функции PHP и расширения без полноты решения: они показаны для контекста и не претендуют на победу среди библиотек.
Честно о плюсах и минусах
Сильные стороны
- Функциональный суперсет: всё, что умеют сравниваемые библиотеки вместе взятые, плюс подпись, шифрование, TTL, сжатие, потоковый формат и маскирование персональных данных.
- Быстрее аналогов во всех измеренных сценариях и заметно экономнее по памяти на маппинге объектов.
- Безопасность заложена в поведение по умолчанию, а не в советы из документации.
- Нет зависимостей: обновление пакета не тянет чужие уязвимости и конфликты версий.
Ограничения, о которых стоит знать
- На простом round-trip массива нативные
serialize()иigbinaryбыстрее: библиотека добавляет проверки, которых у них нет. Если данные заведомо доверенные и нужен максимум скорости — берите нативные функции. - По удерживаемой памяти на round-trip JSON
symfony/serializerнемного экономнее — осознанный компромисс в пользу функциональности и проверок. - YAML поддержан подмножеством спецификации (отображения, списки, скаляры, комментарии): якоря, теги и многодокументные потоки не разбираются.
- Перенос анонимных функций и объектов восстанавливает код, но не привязку
$this, не область видимости класса и не статические свойства; объявление должно быть единственным на строке исходного файла. - Экосистемных интеграций (бандлы, провайдеры фреймворков) пока нет — подключение ручное.
Где применять
| Задача | Рекомендация |
|---|---|
| Очереди и фоновые задачи | Serializer::signed() поверх php() — подделанное сообщение отбрасывается до разбора |
| Cookie и клиентские токены | signed() + expiring() + compressed() — компактно, tamper-proof, с TTL |
| Межсервисный обмен | json() или msgpack() для языковой нейтральности, поверх — подпись |
| Персональные и платёжные данные | encrypted() для хранения, Context::forLogging() для логов |
| Конфигурации приложения | yaml() для правки человеком, exporter() для opcache-кэша |
| Выгрузки и отчёты | csv() с типизированными заголовками, ndjson() для больших наборов |
| Коллекции в миллионы записей | ndjson()->writeTo() и readFrom() — постоянное потребление памяти |
| API с версионированием контракта | mapper() с атрибутами #[Since], #[Until] и группами |
| Недоверенный ввод из внешнего мира | php() без белого списка либо json() — лимиты уже включены |
| Правила и обработчики в конфигурации | dynamic() — замыкания и анонимные объекты переносятся с подписью |
Когда пакет не нужен: одноразовый json_encode() внутри одного процесса,
работа исключительно с доверенными данными без требований к безопасности или
уже настроенный symfony/serializer в Symfony-проекте, где единообразие
с фреймворком важнее перечисленных возможностей.
Разработка
composer install
composer check # линтеры + статический анализ + тесты
composer fix # автоисправления (Rector, PHP CS Fixer, PHPCBF)
composer ci # полный CI-пайплайн локально
composer docs:build # пересборка сравнительных таблиц из реальных прогонов
Полный список команд с описаниями: composer run-script --list.
Документация
- Репозиторий: https://gitverse.ru/cloud-castle/serialize
- Wiki (возможности, архитектура, сравнение): https://gitverse.ru/cloud-castle/serialize/wiki
- История изменений: CHANGELOG.md
- Обновление между версиями: UPGRADING.md
- Как внести вклад: CONTRIBUTING.md
- Кодекс поведения: CODE_OF_CONDUCT.md
- Политика безопасности: SECURITY.md
- Поддержка: SUPPORT.md
Лицензия
MIT © CloudCastle (alex-4-17@yandex.ru)
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano