Введение: вечная дилемма PHP-разработчика
Каждый PHP-разработчик хотя бы раз сталкивался с задачей: "Как сохранить массив в файл, БД или кэш?". На Stack Overflow вопрос "Preferred method to store PHP arrays (json_encode vs serialize)" набрал тысячи просмотров и десятки ответов. И это неудивительно, ведь выбор между json_encode() и serialize() влияет на производительность, совместимость и даже безопасность вашего кода.
В этой статье мы разберем оба метода на реальных примерах, сравним их сильные и слабые стороны, и дадим четкие рекомендации, когда что использовать. Поехали!
Что такое сериализация в PHP?
Сериализация — это процесс преобразования сложной структуры данных (массива, объекта) в строку, которую можно сохранить или передать. Обратный процесс называется десериализацией.
PHP предлагает два основных инструмента для этой задачи:
serialize()/unserialize()— встроенный механизм PHP.json_encode()/json_decode()— работа с форматом JSON.
Казалось бы, оба делают одно и то же. Но дьявол, как всегда, в деталях.
Пример 1: Простой ассоциативный массив
Начнем с самого простого случая — ассоциативного массива с данными пользователя:
<?php
$user = [
'name' => 'Алексей',
'email' => 'alex@example.com',
'age' => 30,
'is_admin' => false
];
// Сериализация
$serialized = serialize($user);
echo $serialized . PHP_EOL;
// Вывод: a:4:{s:4:"name";s:14:"Алексей";s:5:"email";s:17:"alex@example.com";s:3:"age";i:30;s:8:"is_admin";b:0;}
// JSON
$json = json_encode($user, JSON_UNESCAPED_UNICODE);
echo $json . PHP_EOL;
// Вывод: {"name":"Алексей","email":"alex@example.com","age":30,"is_admin":false}
?>
Уже на этом этапе видна разница: serialize() выдает более "грязную" строку с типами данных (s: — строка, i: — целое, b: — булево). JSON же выглядит чисто и читаемо.
Пример 2: Многомерный массив
Давайте усложним задачу и сохраним массив с вложенными данными — например, список товаров в корзине:
<?php
$cart = [
['id' => 101, 'name' => 'Книга "PHP для профи"', 'price' => 1500, 'quantity' => 2],
['id' => 102, 'name' => 'Курс "JSON мастер"', 'price' => 3000, 'quantity' => 1],
['id' => 103, 'name' => 'Сертификат', 'price' => 500, 'quantity' => 3]
];
// Сравним размер строк
$serialized = serialize($cart);
$json = json_encode($cart, JSON_UNESCAPED_UNICODE);
echo "Serialize: " . strlen($serialized) . " байт\n";
echo "JSON: " . strlen($json) . " байт\n";
// Вывод (примерный):
// Serialize: 218 байт
// JSON: 188 байт
?>
Вывод: JSON обычно компактнее, особенно для больших массивов. Это критично при хранении в БД или передаче по сети.
Производительность: что быстрее?
Скорость — один из ключевых факторов. Давайте протестируем на 10 000 итераций:
<?php
$bigArray = [];
for ($i = 0; $i < 1000; $i++) {
$bigArray[] = [
'id' => $i,
'name' => 'Элемент #' . $i,
'data' => range(1, 10)
];
}
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
$s = serialize($bigArray);
$us = unserialize($s);
}
echo "Serialize: " . (microtime(true) - $start) . " сек\n";
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
$j = json_encode($bigArray);
$uj = json_decode($j, true);
}
echo "JSON: " . (microtime(true) - $start) . " сек\n";
?>
Результаты (на PHP 8.2):
- Serialize: ~1.8 сек
- JSON: ~1.2 сек
JSON оказался быстрее примерно на 30-40%. Причина в том, что JSON — более легковесный формат, а serialize() тратит время на упаковку информации о типах.
Безопасность: главный камень преткновения
Здесь serialize() проигрывает с разгромным счетом. Дело в том, что unserialize() может выполнить произвольный код, если передать ему "подозрительную" строку. Это классическая уязвимость PHP-десериализации.
Пример опасного кода:
<?php
// Пользователь может подсунуть такую строку (например, через куки или форму)
$malicious = 'O:12:"MaliciousClass":0:{}';
$obj = unserialize($malicious); // Опасно! Может выполнить __wakeup() или __destruct()
?>
JSON же абсолютно безопасен: json_decode() не вызывает никаких магических методов и не может выполнить код.
Правило: Если данные приходят от пользователя (или из внешнего источника) — используйте только JSON. Для внутреннего кэша можно использовать serialize, но с осторожностью.
Совместимость с другими языками
PHP-сериализация — это "родной" формат PHP. Ни JavaScript, ни Python, ни Java его не понимают. JSON же — универсальный стандарт.
Представьте, что вы пишете API на PHP, а фронтенд на React. Если вы сохраните массив через serialize() и попытаетесь передать его на клиент — браузер его не распарсит. JSON работает везде.
Когда использовать serialize()?
Несмотря на недостатки, у serialize() есть свои козыри:
- Работа с объектами.
serialize()может сохранять объекты вместе с их классами и методами. JSON — только данные. - Сохранение типов. Если вам нужно точно восстановить integer, float или null — serialize справляется лучше. JSON, например, не различает integer и string, если значение выглядит как число.
-
Блоги
Рекомендаций по книгам
Читайте также
Монорепозиторий с Go: организация кода для масштабируемых проектов
A/B тестирование в Rust: как не сломать продакшн и найти истину
Event-driven архитектура на C++: как написать реактивный код
Как написать REST API на Kotlin за 30 минут: для начинающих
Сквозное тестирование Java: от А до Я с реальными примерами