JSON кажется простым форматом, пока не приходит ответ от чужого API. Лишняя запятая, комментарий, одинарные кавычки или NaN — и json_decode() молча возвращает null. В итоге ошибка всплывает позже, в другом месте.

Включайте исключения

С PHP 7.3 у json_decode() есть флаг JSON_THROW_ON_ERROR. Он превращает ошибку разбора в исключение, которое невозможно случайно проигнорировать.

use JsonException;

try {
    $data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
    throw new RuntimeException('Некорректный JSON: ' . $e->getMessage());
}

Без флага проверка выглядит так: json_last_error() !== JSON_ERROR_NONE. Это работает, но легко забыть, особенно если null — допустимое значение.

Ассоциативный массив или объект

Второй аргумент true возвращает массивы вместо объектов. Для шаблонов и foreach удобнее массивы, для строгой типизации — объекты. Главное, не смешивать оба подхода в одном проекте без причины.

$object = json_decode($json, false, 512, JSON_THROW_ON_ERROR);
$array = json_decode($json, true, 512, JSON_THROW_ON_ERROR);

Глубина и большие числа

Третий аргумент ограничивает глубину вложенности. Значение по умолчанию — 512, для обычных API этого достаточно. Слишком большое число может привести к переполнению стека на вредоносном JSON.

Числа в JSON превращаются в float или int. Идентификаторы длиннее 15–16 цифр теряют точность — храните их строками. Для денег используйте целые копейки или строки, а не float.

Кодирование ответа

При сборке JSON включайте читаемые флаги:

$json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);

JSON_UNESCAPED_UNICODE оставляет кириллицу как есть, JSON_UNESCAPED_SLASHES не экранирует ссылки. Для отладки полезен JSON_PRETTY_PRINT, но в API он увеличивает размер ответа.

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

  • Комментарии. В JSON их нет: // и /* */ недопустимы.
  • Одинарные кавычки. Ключи и строки — только в двойных.
  • Запятая перед закрывающей скобкой. Самый частый источник ошибки «Unexpected end of JSON input».
  • undefined, NaN, Infinity. В JSON допустим только null.
  • BOM в начале файла. Некоторые редакторы добавляют невидимый символ, и парсер падает на первом байте.

Проверка перед отправкой

Если JSON собирается вручную или приходит из формы, проверьте его до сохранения. JSON-форматтер показывает номер строки и символа, где произошла ошибка, — это быстрее, чем искать запятую глазами.

Коротко

  • всегда используйте JSON_THROW_ON_ERROR;
  • не храните деньги и длинные ID в числах;
  • проверяйте глубину и размер входных данных;
  • для ответа API включайте JSON_UNESCAPED_UNICODE;
  • ошибку JSON показывайте с позицией, а не общим «не удалось».