Изменения JSON в восьмой версии PHP: практические примеры
Изменения в работе с JSON в PHP 8
Ключевые нововведения PHP 8 в области JSON касаются улучшенной обработки ошибок и новых флагов для управления кодированием и декодированием. Основное эффективное решение - использование исключений JsonException с флагом JSON_THROW_ON_ERROR.
Основной подход: исключения вместо проверки кода ошибки
Начиная с PHP 7.3 появилась возможность выбрасывать исключение при ошибках JSON, но в PHP 8 этот механизм стал стандартом и рекомендуется для всех новых проектов. Это позволяет писать более чистый и предсказуемый код.
$json = '{"name": "PHP 8"}';
try {
$data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
echo $data['name']; // PHP 8
} catch (JsonException $e) {
echo 'Ошибка JSON: ' . $e->getMessage();
}
Php 8 request (особенности обработки запросов в php 8)
В данном примере при успешном декодировании выводится значение ключа. Если JSON некорректен, вместо возврата null будет выброшено исключение, что упрощает отладку.
Возможная проблема и её решение
Если не указать флаг JSON_THROW_ON_ERROR, при ошибке функция возвращает null, и разработчик может не заметить проблему. Решение - всегда использовать этот флаг в новом коде.
Как обработать ошибки JSON без исключений?
Классический подход с проверкой json_last_error() остаётся рабочим, но более громоздкий. Он может быть полезен в легаси-проектах или там, где исключения нежелательны.
$json = '{"invalid"}';
$data = json_decode($json);
if (json_last_error() !== JSON_ERROR_NONE) {
echo 'Ошибка: ' . json_last_error_msg();
}
Php 8.4 windows (php 8.4 на windows)
После вызова json_decode нужно вручную проверить код ошибки. Минус - легко забыть эту проверку, что приводит к скрытым багам.
Типичная ошибка: вызов json_decode без проверки, полагаясь на строгую типизацию
Если ожидается массив, но возвращается null, код выдаст фатальную ошибку при попытке обратиться к индексу. Решение - всегда проверять результат или использовать JSON_THROW_ON_ERROR.
Как управлять кодировкой UTF-8 в JSON?
PHP 8 поддерживает флаги JSON_INVALID_UTF8_IGNORE и JSON_INVALID_UTF8_SUBSTITUTE, позволяющие контролировать поведение при некорректных байтах UTF-8.
$string = "\x80"; // некорректный байт UTF-8
echo json_encode($string, JSON_INVALID_UTF8_SUBSTITUTE);
// выведет "\ufffd" (символ замены)
Php 7 функции (новые функции php 7)
Флаг JSON_INVALID_UTF8_IGNORE пропускает некорректные символы, JSON_INVALID_UTF8_SUBSTITUTE заменяет их на U+FFFD. Это полезно при обработке данных из внешних источников.
Проблема: json_encode возвращает false при недопустимых байтах
Без указанных флагов кодирование завершится ошибкой. Решение - добавить соответствующий флаг или предварительно очистить входные данные.
Как ограничить глубину рекурсии при декодировании?
По умолчанию глубина вложенности ограничена 512. В PHP 8 можно изменить это значение через параметр depth.
$json = str_repeat('{"a":', 1000) . '1' . str_repeat('}', 1000);
$data = json_decode($json, true, 1000, JSON_THROW_ON_ERROR);
Если глубина превышает лимит, выбрасывается исключение. Это защищает от переполнения стека.
Ошибка: превышение максимальной глубины
При получении данных из ненадёжного источника можно столкнуться с искусственно глубокой структурой. Решение - установить разумный лимит глубины, например 100, и использовать исключение.
Расширенные примеры работы с JSON в PHP 8
Пример 1: Декодирование с ассоциативным массивом и строгими типами
$json = '{"count": 100, "active": true}';
$data = json_decode($json, true, 512, JSON_THROW_ON_ERROR | JSON_OBJECT_AS_ARRAY);
echo gettype($data['count']); // integer
Результат: integer. Флаг JSON_OBJECT_AS_ARRAY гарантирует, что объекты будут преобразованы в массивы даже при отсутствии второго аргумента.
Пример 2: Кодирование с отступами для красивого вывода
$data = ['name' => 'PHP 8', 'version' => 8.0];
$json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
echo $json;
Результат:
{
"name": "PHP 8",
"version": 8
}
Флаг JSON_UNESCAPED_UNICODE сохраняет символы Unicode, JSON_PRETTY_PRINT форматирует вывод.
Пример 3: Обработка циклических ссылок
$obj = new stdClass();
$obj->self = $obj;
try {
echo json_encode($obj, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
echo 'Ошибка: ' . $e->getMessage(); // Recursion detected
}
PHP 8 выбрасывает JsonException при попытке кодировать рекурсивную структуру. Ранее это вызывало фатальную ошибку.
Пример 4: Использование константы JSON_THROW_ON_ERROR в json_encode
$data = ['key' => "\xB1\x31"]; // некорректная UTF-8 последовательность
$result = @json_encode($data, JSON_THROW_ON_ERROR | JSON_INVALID_UTF8_IGNORE);
if ($result === false) {
// уже не нужно, исключение перехватывается выше
}
echo $result; // {"key":"?1"} (если замена, зависит от флага)
С флагом JSON_INVALID_UTF8_IGNORE некорректные байты пропускаются. Обратите внимание: @ подавляет предупреждения, но исключение всё равно выбрасывается.
Пример 5: Пользовательский обработчик через JsonSerializable
class User implements JsonSerializable {
public function __construct(private string $name, private string $email) {}
public function jsonSerialize(): mixed {
return [
'name' => $this->name,
'email' => $this->email,
];
}
}
$user = new User('Alice', 'alice@example.com');
echo json_encode($user, JSON_THROW_ON_ERROR);
// {"name":"Alice","email":"alice@example.com"}
Интерфейс JsonSerializable позволяет объекту определять собственное представление для JSON. Это особенно удобно при работе с DTO или моделями.