Методы записи JSON в файл средствами PHP
Сохранение JSON в файл является частой задачей при работе с PHP. Основной и наиболее эффективный способ - использование функции file_put_contents в сочетании с json_encode. Этот метод объединяет создание или перезапись файла и запись данных одной строкой, минимально расходуя ресурсы.
$data = ['user' => 'Иван', 'age' => 30, 'roles' => ['admin', 'editor']];
$json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
file_put_contents('data.json', $json);
Php сохранить json (сохранение json в файл на php)
Параметр JSON_UNESCAPED_UNICODE предотвращает преобразование кириллицы в юникод-последовательности (\uXXXX), а JSON_PRETTY_PRINT форматирует вывод с отступами, делая файл читаемым для человека.
Типичная ошибка: отсутствие прав на запись в папку. Решение - проверка is_writable() перед записью или установка корректных прав chmod. Другая проблема - недопустимые значения в данных (например, ресурсы или объекты без JsonSerializable). В этом случае json_encode вернёт false, что нужно проверять.
Как выполнить запись с пошаговым контролем каждого этапа?
Использование пары fopen / fwrite / fclose даёт возможность управлять буферизацией и проверять промежуточные результаты.
$file = fopen('data.json', 'w');
if ($file) {
$json = json_encode($data, JSON_UNESCAPED_UNICODE);
fwrite($file, $json);
fclose($file);
} else {
// обработка ошибки
}
Такой подход полезен при необходимости дописывать данные частями или использовать нестандартные потоки.
Ошибка: забытый вызов fclose приводит к утечке дескриптора. Для предотвращения стоит оборачивать код в try-finally или использовать автоматическое закрытие через file_put_contents.
Как избежать повреждения файла при одновременном доступе?
При многопоточности или параллельных запросах к одному файлу следует применить блокировку flock.
$file = fopen('data.json', 'c');
if (flock($file, LOCK_EX)) {
$json = json_encode($data, JSON_UNESCAPED_UNICODE);
ftruncate($file, 0); // очистка
fwrite($file, $json);
flock($file, LOCK_UN);
}
fclose($file);
Режим 'c' не урезает файл при открытии, а ftruncate очищает его перед записью.
Ошибка: если блокировка не освобождена, другие процессы будут ждать или получат отказ. Всегда следует использовать LOCK_UN или дождаться завершения.
Как перехватить ошибки кодирования JSON?
Начиная с PHP 7.3 можно указать флаг JSON_THROW_ON_ERROR, чтобы вместо возврата false выбрасывалось исключение.
try {
$json = json_encode($data, JSON_THROW_ON_ERROR);
file_put_contents('data.json', $json);
} catch (JsonException $e) {
// логирование или уведомление
}
Цель - безусловное обнаружение ошибок сериализации на этапе разработки.
Проблема: в более старых версиях PHP константа не определена. Аналог - ручная проверка json_last_error().
Как автоматически создавать папку для файла?
Если целевая директория может отсутствовать, её нужно создать рекурсивно через mkdir.
$path = 'backups/data.json';
$dir = dirname($path);
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
file_put_contents($path, json_encode($data, JSON_UNESCAPED_UNICODE));
Параметр true в mkdir разрешает создание вложенных папок.
Ошибка: недостаточно прав на создание директории. Решение - проверка успешности mkdir или предварительная настройка прав.
Как добавить метаданные (время, версию) в имя файла?
Для хранения истории изменений можно динамически формировать имя, включая метку времени.
$filename = 'data_' . date('Ymd_His') . '.json';
file_put_contents($filename, json_encode($data, JSON_PRETTY_PRINT));
Такой подход удобен для резервного копирования или аудита.
Предостережение: при большом количестве файлов может потребоваться ротация или очистка. Также возможно пересечение имён при одновременных операциях в одну секунду - стоит добавить микросекунды (u).
Расширенные примеры сохранения JSON
Пример 1: Поточная запись больших массивов
Если данные очень велики и не помещаются в память, следует кодировать и записывать поэтапно. Ниже пример с использованием генератора.
function generateLargeArray(): Generator {
for ($i = 0; $i < 100000; $i++) {
yield ['id' => $i, 'value' => str_repeat('x', 1000)];
}
}
$file = fopen('large.json', 'w');
fwrite($file, '[');
$first = true;
foreach (generateLargeArray() as $item) {
if (!$first) fwrite($file, ',');
fwrite($file, json_encode($item, JSON_UNESCAPED_UNICODE));
$first = false;
}
fwrite($file, ']');
fclose($file);
Файл large.json содержит валидный JSON-массив из 100 000 элементов, сформированный без полной загрузки в память.
Пример 2: Сохранение с шифрованием содержимого
Для хранения конфиденциальных данных можно закодировать JSON в base64 (но учтите, что это не защита, а лишь преобразование).
$data = ['password' => 'secret'];
$json = json_encode($data);
$encoded = base64_encode($json);
file_put_contents('secret.data', $encoded);
Содержимое файла secret.data: eyJwYXNzd29yZCI6InNlY3JldCJ9
Пример 3: Пользовательский класс с интерфейсом JsonSerializable
Объекты, реализующие JsonSerializable, могут управлять своей JSON-сериализацией.
class User implements JsonSerializable {
public function __construct(
private string $name,
private int $age,
private string $password // не включать в JSON
) {}
public function jsonSerialize(): mixed {
return ['name' => $this->name, 'age' => $this->age];
}
}
$user = new User('Анна', 28, 'hidden');
file_put_contents('user.json', json_encode($user, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
{
"name": "Анна",
"age": 28
}
Пример 4: Сохранение с кастомными опциями и сравнение размера
Использование разных комбинаций флагов влияет на размер и читаемость файла.
$data = ['url' => 'https://example.com/path?q=test&lang=ru'];
$compact = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$pretty = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
file_put_contents('compact.json', $compact);
file_put_contents('pretty.json', $pretty);
echo 'Compact size: ' . strlen($compact) . ' bytes\n';
echo 'Pretty size: ' . strlen($pretty) . ' bytes';
Compact size: 55 bytes Pretty size: 76 bytes
Пример 5: Запись в удалённый ресурс через обёртку потока
PHP позволяет записывать данные не только в локальный файл, но и, например, на FTP-сервер.
$json = json_encode($data);
$options = ['ftp' => [
'overwrite' => true,
'username' => 'user',
'password' => 'pass'
]];
$stream = fopen('ftp://example.com/data.json', 'w', false, stream_context_create($options));
fwrite($stream, $json);
fclose($stream);
Файл data.json будет записан на удалённый FTP-сервер при корректных учётных данных.