JSON или Serialize: что выбрать для хранения массивов PHP? (полный гайд)

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: вечная дилемма 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() есть свои козыри: