Работа с JSON-файлами в PHP: от основ до продвинутых техник

Раздел: Работа с файлами -> Чтение и запись JSON

Основы работы с JSON-файлами в PHP

Наиболее эффективный способ чтения и записи JSON-файлов в PHP - использование пары функций file_get_contents и file_put_contents вместе с json_decode и json_encode. Этот подход позволяет минимизировать количество операций ввода-вывода и работает с любым типом данных, которые могут быть представлены в JSON.


// Чтение JSON из файла
$jsonString = file_get_contents('data.json');
$data = json_decode($jsonString, true);

// Обработка ошибки декодирования
if (json_last_error() !== JSON_ERROR_NONE) {
    throw new RuntimeException('Ошибка декодирования JSON: ' . json_last_error_msg());
}

// Изменение данных (пример)
$data['counter']++;

// Запись обратно в файл
$newJsonString = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
file_put_contents('data.json', $newJsonString);
  

Json php файл (php: работа с json-файлом)

Пояснение шагов:

  • file_get_contents - читает весь файл в строку. Подходит для файлов небольшого и среднего размера.
  • json_decode($string, true) - преобразует JSON в ассоциативный массив. Второй аргумент true гарантирует получение массива, а не объекта.
  • json_last_error() - проверяет успешность декодирования. Значение JSON_ERROR_NONE говорит об отсутствии ошибок.
  • json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) - преобразует массив обратно в JSON с форматированием (отступы) и сохраняет кириллицу.
  • file_put_contents - атомарно записывает строку в файл, создавая его при необходимости.

Как прочитать JSON из файла, используя потоковые функции fopen и fread?

Этот вариант полезен, когда нужно обрабатывать файл по частям или контролировать позицию чтения.


$handle = fopen('data.json', 'r');
if (!$handle) {
    throw new RuntimeException('Не удалось открыть файл');
}
$jsonString = '';
while (!feof($handle)) {
    $jsonString .= fread($handle, 1024);
}
fclose($handle);

$data = json_decode($jsonString, true);
  

Типичные ошибки:

  • Забыть проверить результат fopen - может привести к ошибке чтения.
  • Неправильный режим доступа (например 'w' вместо 'r') - уничтожит содержимое файла.
  • Использование цикла без проверки feof - может вызвать бесконечный цикл при повреждённом файле.

Как записать JSON в файл, используя fwrite?

Подходит для случаев, когда нужно дописывать данные или использовать блокировки.


$data = ['name' => 'Иван', 'age' => 30];
$jsonString = json_encode($data, JSON_UNESCAPED_UNICODE);

$handle = fopen('output.json', 'w');
if (flock($handle, LOCK_EX)) {
    fwrite($handle, $jsonString);
    flock($handle, LOCK_UN);
}
fclose($handle);
  

Проблемы:

  • Без использования flock при параллельных запросах может произойти повреждение данных.
  • Запись в несуществующую директорию - нужно предварительно создать её.

Как обработать ошибки JSON с помощью исключений?

Использование флага JSON_THROW_ON_ERROR в PHP 7.3+ позволяет вместо проверки json_last_error() получать исключение.


try {
    $data = json_decode(file_get_contents('data.json'), true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
    error_log('Ошибка JSON: ' . $e->getMessage());
    // альтернативные действия
}
  

Важно:

  • Данный способ исключает необходимость писать условные конструкции с json_last_error().
  • Однако он не перехватывает ошибки самого файлового ввода-вывода - их нужно обрабатывать отдельно.

Как загрузить JSON из удалённого источника (URL)?

Если файл находится на другом сервере, можно использовать file_get_contents с URL, либо cURL для более тонкого контроля.


$url = 'https://api.example.com/data.json';
$context = stream_context_create(['http' => ['timeout' => 10]]);
$jsonString = file_get_contents($url, false, $context);
if ($jsonString === false) {
    throw new RuntimeException('Не удалось получить данные с удалённого сервера');
}
$data = json_decode($jsonString, true);
  

Возможные сложности:

  • Необходимость включения директивы allow_url_fopen в php.ini.
  • Ограничение времени ожидания (timeout) при медленном соединении.
  • Обработка HTTP-статусов (например, 404) - file_get_contents не умеет отличать ошибку от пустого ответа.

Расширенные примеры работы с JSON-файлами

Пример 1. Чтение и обновление конфигурационного файла

Пример

$configFile = 'config.json';

// Чтение
$config = json_decode(file_get_contents($configFile), true);

// Изменение
$config['version'] = '2.0';
$config['last_updated'] = date('Y-m-d H:i:s');

// Запись с блокировкой
$tempFile = $configFile . '.tmp';
file_put_contents($tempFile, json_encode($config, JSON_PRETTY_PRINT));
rename($tempFile, $configFile); // атомарная замена
// Содержимое config.json после выполнения:
{
    "version": "2.0",
    "last_updated": "2025-03-18 14:22:10",
    "other": "..."
}

Данный подход гарантирует, что файл не будет повреждён в случае сбоя во время записи.

Пример 2. Сохранение массива данных из формы

Пример

$newEntry = [
    'name' => $_POST['name'],
    'email' => $_POST['email'],
    'timestamp' => time()
];

// Загрузка существующих записей
$file = 'submissions.json';
$existing = file_exists($file) ? json_decode(file_get_contents($file), true) : [];

// Добавление новой записи
$existing[] = $newEntry;

// Перезапись
file_put_contents($file, json_encode($existing, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
// submissions.json:
[
    {
        "name": "Анна",
        "email": "anna@example.com",
        "timestamp": 1710765600
    },
    {
        "name": "Иван",
        "email": "ivan@example.com",
        "timestamp": 1710765700
    }
]

Пример 3. Обработка большой JSON-структуры с вложенными объектами

Пример

$complexData = [
    'users' => [
        ['id' => 1, 'roles' => ['admin', 'editor']],
        ['id' => 2, 'roles' => ['subscriber']]
    ],
    'metadata' => [
        'generated' => date('c'),
        'version' => '1.0'
    ]
];

// Запись с флагом JSON_FORCE_OBJECT для числовых ключей (если нужно)
$json = json_encode($complexData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
file_put_contents('complex.json', $json);

// Чтение и поиск пользователя
$restored = json_decode(file_get_contents('complex.json'), true);
$adminUsers = array_filter($restored['users'], fn($u) => in_array('admin', $u['roles']));
print_r($adminUsers);
Array
(
    [0] => Array
        (
            [id] => 1
            [roles] => Array
                (
                    [0] => admin
                    [1] => editor
                )
        )
)

Пример 4. Использование JSON_THROW_ON_ERROR и проверка целостности данных

Пример

try {
    $raw = file_get_contents('corrupted.json');
    if ($raw === false) {
        throw new RuntimeException('Не удалось прочитать файл');
    }
    $data = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException | RuntimeException $e) {
    error_log($e->getMessage());
    // Восстановление из резервной копии
    $data = json_decode(file_get_contents('backup.json'), true);
}

Применяется в критичных системах, где потеря данных недопустима.

Пример 5. Построчное чтение большого JSON-файла (JSON Lines)

Пример

$handle = fopen('large.ndjson', 'r');
if (!$handle) die('Cannot open file');

while (($line = fgets($handle)) !== false) {
    $record = json_decode(trim($line), true);
    if ($record === null && json_last_error() !== JSON_ERROR_NONE) {
        continue; // пропускаем битые строки
    }
    // обработка записи $record
}
fclose($handle);

Формат NDJSON (Newline Delimited JSON) позволяет обрабатывать гигабайтные файлы без загрузки в память.

PHP: работа с JSON-файлом - comments

En
Json php файл (php)