cloud-castle / parser-json
Безопасный разбор и сериализация JSON для PHP 8.1+: исключения вместо тихого null, лимит глубины, безопасные дефолты кодирования и типизированные помощники. Единственная зависимость — ext-json.
Requires
- php: >=8.1
- ext-json: *
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.1 || ^2.0
Requires (Dev)
- 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
- laminas/laminas-json: ^3.5
- nette/utils: ^4.0
- nyholm/psr7: ^1.8
- 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
- vimeo/psalm: ^6.0
- webmozart/assert: ^1.11
This package is auto-updated.
Last update: 2026-07-29 09:11:57 UTC
README
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano
CloudCastle Parser Json
Безопасный разбор и сериализация JSON для PHP 8.1+: всегда бросает исключение при ошибке (не тихий
null), лимит глубины вложенности, безопасные дефолты кодирования и типизированные помощники. Исключения не содержат исходных данных — безопасно для логов с персональными данными. Единственная зависимость —ext-json.
Установка
composer require cloud-castle/parser-json
Требуется PHP 8.1+ и расширение ext-json.
Быстрый старт
<?php
use CloudCastle\Parser\Json\Json;
// Разбор в ассоциативные массивы — при ошибке бросается MalformedJsonException.
$data = Json::decode('{"user":{"id":42},"tags":["a","b"]}');
// Гарантированно массив на верхнем уровне (иначе исключение).
$list = Json::toArray('[1,2,3]');
// Разбор объектов как stdClass.
$object = Json::decodeObject('{"id":42}');
// Сериализация с безопасными дефолтами (читаемый юникод, без экранирования слэшей).
$json = Json::encode(['url' => 'http://a/b', 'имя' => 'Значение']);
// {"url":"http://a/b","имя":"Значение"}
// Человекочитаемый вывод с отступами.
echo Json::pretty(['a' => 1, 'b' => [2, 3]]);
// Проверка без исключения.
if (Json::isValid($input)) {
// ...
}
// Ограничение глубины вложенности (защита от глубоких структур).
$safe = Json::decode($untrusted, depth: 8);
// Разбор из локального файла.
$data = Json::decodeFile('/path/to/data.json');
// Автоопределение источника: локальный путь или URL. Загрузка по URL
// делегируется PSR-18 клиенту (лимит размера, таймауты и защита от SSRF —
// на стороне клиента, например cloud-castle/http-client).
$data = Json::decodeFrom('https://example.com/data.json', $httpClient, $requestFactory);
$data = Json::decodeFrom('/path/to/data.json'); // тот же метод — локальный файл
Возможности
- Fail-loud: любая ошибка разбора или сериализации — исключение
(
MalformedJsonException/EncodingException), а не молчаливыйnull/false, который легко пропустить. - Лимит глубины вложенности (по умолчанию 512) — защита от переполнения стека на злонамеренно/случайно глубоких структурах.
- Безопасные дефолты кодирования:
JSON_UNESCAPED_UNICODE(читаемый юникод) иJSON_UNESCAPED_SLASHES(без лишнего экранирования). - Исключения не содержат исходных данных — только причину сбоя, чтобы персональные и финансовые данные из JSON не утекли в логи и трассировки.
- Типизированные помощники:
toArray()гарантирует массив,decodeObject()— объектную форму,isValid()— проверку без исключения. - Загрузка из файла и по URL:
decodeFile()(локальный файл) иdecodeFrom()(автоопределение локального пути или URL). Сеть не встроена — загрузка по URL идёт через инъектируемый PSR-18 клиент, где и задаются лимит размера, таймауты и защита от SSRF (например,cloud-castle/http-client). - Единственная runtime-зависимость — расширение
ext-json(контракты PSR-18/17 нужны только для загрузки по URL).
Коротко
Безопасная обёртка над ext-json для разбора JSON из недоверенных источников:
fail-loud вместо тихого null, лимит глубины, типизированные помощники и исключения
без исходных данных (безопасно для логов с ПД), плюс загрузка из файла/URL с
контролем размера и SSRF. Лидер по функционалу, скорости и безопасности среди
JSON-обёрток; по памяти — наравне со всеми (разбор даёт идентичную структуру).
Сравнение с аналогами
Все таблицы ниже сгенерированы автоматически из честных сравнительных
тестов (benchmarks/compare.php) на ОДИНАКОВОЙ операции для всех аналогов,
PHP 8.1.34, без Xdebug.
1. Функциональность
| Возможность | 🏆 CloudCastle | symfony | nette | laminas | json¹ |
|---|---|---|---|---|---|
| Исключение при любой ошибке (не тихий null/false) | ✅ | ✅ | ✅ | ✅ | ❌ |
| Лимит глубины вложенности (защита от глубоких структур) | ✅ | ✅ | ✅ | ❌ | ✅ |
| Типизированные помощники (toArray/decodeObject) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Исключения не содержат исходных данных (безопасно для логов с ПД) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Ноль зависимостей сверх ext-json | ✅ | ❌ | ❌ | ❌ | ✅ |
| Загрузка из файла/URL с контролем размера и SSRF (PSR-18) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Всего | 🏆 6 | 2 | 2 | 1 | 2 |
2. Безопасность и корректность
| Свойство | 🏆 CloudCastle | symfony | nette | laminas | json¹ |
|---|---|---|---|---|---|
| Fail-loud: исключение вместо пропущенного null по умолчанию | ✅ | ✅ | ✅ | ✅ | ❌ |
| Лимит глубины (защита от переполнения стека на глубоком JSON) | ✅ | ✅ | ✅ | ❌ | ✅ |
| Исключения не раскрывают исходные данные (нет утечки ПД в логи) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Читаемый юникод без искажения (JSON_UNESCAPED_UNICODE) | ✅ | ✅ | ✅ | ❌ | ❌ |
| Проверка типа результата (toArray отвергает неожиданный корень) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Всего | 🏆 5 | 3 | 3 | 1 | 1 |
3. Производительность
encode + decode структуры данных, 100 000 раз (минимум из 4).
| Решение | Время (мс) | Итог |
|---|---|---|
| json¹ | 692,4 | базовый уровень (не библиотека) |
| 🏆 CloudCastle | 1 323,4 | быстрейшее среди библиотек |
| nette | 1 354,7 | аналог |
| symfony | 1 973,7 | аналог |
| laminas | 2 324,9 | аналог |
4. Потребление памяти
Фактически занятая память 100 000 удержанных результатов разбора (изолированный процесс).
| Решение | Пиковая память (KB) | Итог |
|---|---|---|
| 🏆 symfony | 193 944 | легчайшее среди библиотек |
| json¹ | 193 944 | базовый уровень (не библиотека) |
| nette | 193 953 | аналог |
| CloudCastle | 193 968 | аналог |
| laminas | 193 981 | аналог |
¹ Базовый уровень (нативные вызовы/примитивы без полноты решения) показан для контекста и не претендует на победу среди библиотек-аналогов.
О памяти честно. Замер — фактически занятая память (
memory_get_usage) при удержании 100 000 результатов разбора в изолированном процессе. Все JSON-парсеры декодируют в идентичную структуру данных, поэтому память на удержание результата у всех одинакова (различия <0,02% — в пределах шума). Память здесь не различающая ось; реальные различия — в скорости (пакет быстрейший) и функционале/безопасности (пакет лидер).
Плюсы, минусы и когда применять
Сильные стороны:
- Функционал = объединение аналогов — единственный совмещает fail-loud,
лимит глубины, типизированные помощники, безопасные исключения (без исходных
данных), загрузку из файла/URL с контролем размера и SSRF — при нуле зависимостей
сверх
ext-json. - Быстрейший разбор среди библиотек — быстрее
symfony/serializer,nette/utils,laminas-json; вплотную к «голому»ext-json(baseline). - Безопасность — исключение вместо тихого
null/false, лимит глубины (защита от переполнения стека), исключения не раскрывают исходные данные — безопасно для логов с ПД (лидер по таблице безопасности). - Память — наравне с самыми лёгкими: разбор даёт идентичную структуру, расход одинаков у всех (различия в пределах шума).
Слабые стороны (честно):
- Тонкая обёртка над
ext-json— не самостоятельный парсер; при экзотических требованиях к производительности «голый»json_decodeминимально быстрее (ценой тихих ошибок и отсутствия защит). - Не сериализатор объектов — для маппинга JSON ↔ типизированные DTO берите
symfony/serializer(здесь фокус на безопасном разборе данных, а не на гидрации).
Когда применять. Везде, где JSON приходит из недоверенного источника (API,
конфиги, очереди) и важны предсказуемая обработка ошибок, защита от глубоких структур
и отсутствие утечки персональных данных в логи. Для маппинга в типизированные объекты —
symfony/serializer; для микро-выигрыша скорости ценой безопасности — ext-json.
Разработка
composer install
composer check # линтеры + статический анализ + тесты
composer fix # автоисправления (Rector, PHP CS Fixer, PHPCBF)
composer ci # полный CI-пайплайн локально
Полный список команд с описаниями: composer run-script --list.
Документация
- Репозиторий: https://gitverse.ru/cloud-castle/parser-json
- История изменений: CHANGELOG.md
- Как внести вклад: CONTRIBUTING.md
- Кодекс поведения: CODE_OF_CONDUCT.md
- Политика безопасности: SECURITY.md
Лицензия
MIT © CloudCastle (alex-4-17@yandex.ru)
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano