Avatar ·

Как лучше хранить массивы PHP: json_encode против serialize? Сравнение и производительность

Всем привет! Я новичок в PHP и пытаюсь разобраться с хранением массивов. У меня есть несколько скриптов, которые обрабатывают данные из базы данных, и я хочу кешировать результаты в файлах, чтобы не делать тяжелые запросы каждый раз. Проблема в том, что я не могу выбрать между json_encode и serialize. Оба подходят для преобразования массива в строку, но я не понимаю, в чем разница и какой из них лучше использовать. Вот пример моего кода: ```php $data = [ 'users' => [ ['id' => 1, 'name' => 'Иван', 'email' => 'ivan@example.com'], ['id' => 2, 'name' => 'Мария', 'email' => 'maria@example.com'], ['id' => 3, 'name' => 'Петр', 'email' => 'petr@example.com'] ], 'timestamp' => time(), 'settings' => ['theme' => 'dark', 'lang' => 'ru'] ]; // Вариант 1 $json = json_encode($data); file_put_contents('cache.json', $json); // Вариант 2 $serialized = serialize($data); file_put_contents('cache.ser', $serialized); ``` Меня интересуют следующие аспекты: 1. Какой метод быстрее работает? 2. Какой метод создает меньший по размеру файл? 3. Какой из них безопаснее для хранения данных? 4. Есть ли ограничения на типы данных, которые можно сериализовать? 5. Что лучше для передачи данных между разными системами? Я прочитал несколько статей, но мнения разделились. Одни говорят, что serialize быстрее, другие — что json_encode компактнее. Помогите разобраться! Заранее спасибо. <<>>

Сравнение json_encode и serialize: подробный разбор

Отличный вопрос! Давайте разберем оба метода по косточкам. Начну с главного: не существует универсально лучшего метода — выбор зависит от вашей задачи.

1. Производительность (скорость)

В большинстве современных версиях PHP (7.4+) serialize работает на 20-40% быстрее для простых массивов. Однако json_encode быстрее для сложных вложенных структур. Рекомендую протестировать на своих данных:

// Тест производительности
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
    $json = json_encode($data);
}
echo 'json_encode: ' . (microtime(true) - $start) . ' сек';

$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
    $ser = serialize($data);
}
echo 'serialize: ' . (microtime(true) - $start) . ' сек';

2. Размер данных

json_encode обычно создает меньший по размеру файл (на 10-30%). Это связано с тем, что JSON не хранит информацию о типах данных и длине строк. Пример:

$data = [
    'name' => 'Александр',
    'age' => 30,
    'active' => true
];

echo strlen(json_encode($data)); // 47 байт
echo strlen(serialize($data));    // 69 байт

3. Безопасность

JSON безопаснее. unserialize() может выполнить произвольный код при десериализации недоверенных данных (известная уязвимость). Никогда не используйте unserialize() для данных из пользовательского ввода! json_decode() безопасен — он создает только простые объекты/массивы.

4. Поддержка типов данных

serialize поддерживает все типы PHP, включая:

  • Объекты (с сохранением класса)
  • Ресурсы (но их нельзя сериализовать)
  • NULL, булевы значения
  • Специальные типы (например, SimpleXML)

json_encode поддерживает только:

  • Скаляры (int, float, string, bool, null)
  • Массивы
  • Объекты (с публичными свойствами)

Важно: json_encode преобразует все ключи массивов в строки, а serialize сохраняет оригинальные типы ключей.

5. Совместимость с другими системами

JSON — стандарт де-факто для обмена данными между системами. Его читают JavaScript, Python, Java и любой другой язык. serialize — это внутренний формат PHP, который нельзя использовать за пределами экосистемы PHP.

Практические рекомендации

  • Для кеширования данных внутри PHP — используйте serialize (быстрее, сохраняет типы)
  • Для хранения конфигураций или данных, которые будут читаться не из PHP — используйте json_encode
  • Для пользовательского ввода или данных из внешних источников — только json_decode (безопасность)
  • Для больших объемов данных — тестируйте оба метода, так как производительность зависит от структуры данных

Пример правильного кеширования с serialize:

function getCachedData($key) {
    $file = "cache/{$key}.cache";
    if (file_exists($file) && (time() - filemtime($file)) < 3600) {
        return unserialize(file_get_contents($file));
    }
    
    $data = heavyDatabaseQuery();
    file_put_contents($file, serialize($data));
    return $data;
}

И с JSON для конфигурации:

function loadConfig() {
    $json = file_get_contents('config.json');
    return json_decode($json, true); // true для получения массива
}
<<>>

Альтернативный подход: igbinary и другие сериализаторы

Если производительность критична, рассмотрите igbinary — это расширение PHP, которое заменяет стандартный сериализатор. Оно работает в 2-3 раза быстрее и создает файлы на 30-50% меньше, чем serialize.

// С igbinary
$data = igbinary_serialize($array);
$array = igbinary_unserialize($data);

// Для файлового кеша
file_put_contents('cache.igb', igbinary_serialize($data));
$data = igbinary_unserialize(file_get_contents('cache.igb'));

Плюсы igbinary:

  • Значительно быстрее стандартного serialize
  • Меньший размер данных
  • Поддерживает все типы PHP

Минусы:

  • Требует установки расширения (не входит в стандартную поставку PHP)
  • Не совместим с другими языками
  • Может быть проблемы при обновлении PHP (обратная совместимость не гарантируется)

Еще один вариант — MessagePack (через расширение msgpack). Он дает бинарный формат, похожий на JSON, но компактнее и быстрее. Хорошо подходит для передачи данных между PHP и Python/Ruby.

Итог: Для большинства проектов хватит json_encode (безопасность, совместимость) или serialize (скорость, типы). igbinary — нишевое решение для высоконагруженных систем, где каждый миллисекунда на счету.

Советую начать с JSON — это самый универсальный и безопасный вариант. Переходите на serialize только если замеры покажут, что JSON является узким местом производительности.