Александр Некрасов · Автономное руководство

PHP: полный мануал с примерами, функциями и ООП

Разделы этой страницы
  1. JSON: функции, флаги, ошибки и формат обмена
  2. JSON — общий текстовый формат для разных программ
  3. Какие значения можно передавать
  4. Установка, версии и точность чисел
  5. Две модели ошибки: результат или исключение
  6. JsonException: что хранится в объекте ошибки
  7. Флаги: выбирать по договору, а не включать все сразу
  8. Все категории JSON_ERROR_*
  9. Как объект определяет публичное JSON-представление
  10. Граница интеграции: синтаксис, схема и транспорт
  11. Все функции и интерфейс JSON
  12. Функции и методы этой темы
  13. Код и руководство с собой
PHP 8.5.11149 глав4458 карточек справочника
Дерево руководства

Глава 149 · С нуля → справочник

JSON: функции, флаги, ошибки и формат обмена

Полная категория JSON: кодирование и разбор, проверка синтаксиса, все флаги и коды ошибок, JsonException и публичное представление объектов.

JSON — общий текстовый формат для разных программ

Наглядная модель

Из числа 0 в JSON-текст и обратно

Первый опыт не требует ни массива, ни сети. Он показывает смену представления одного и того же остатка товара.

  1. $stock = 0

    PHP хранит int: целое число.

  2. json_encode($stock)

    Возвращает string "0" — текст из одного байта.

  3. $text = …

    Строка сохранена; транспорт или файл могут передать её другой программе.

  4. json_decode($text)

    Разбирает текст и возвращает PHP int 0.

  5. $restored = …

    var_dump показывает int(0), а не строку.

JSON-кодирование и декодирование не выполняют HTTP-запросы. Правильный синтаксис не доказывает, что пришёл допустимый заказ или показание датчика.

PHP-массив живёт внутри PHP. Мобильное приложение, Node.js и контроллер на объекте не умеют читать его внутреннее устройство. Они договариваются передавать текст в известном формате — например JSON. json_encode создаёт такой текст из PHP-значения; json_decode читает текст и создаёт PHP-значение. Ни одна из этих функций сама не отправляет HTTP-запрос.

Один остаток товара проходит границу программ
  1. PHP: $stock = 0 — целое число.
  2. json_encode($stock) → PHP-строка "0", содержащая JSON-число.
  3. Передача/хранение — отдельный шаг, которого в первом опыте нет.
  4. json_decode($text) → снова PHP int 0.
Начать с одного числа, без массива и сетевого запросаСамостоятельный пример
<?php
$stock = 0;
$text = json_encode($stock);
var_dump($text);
$restored = json_decode($text);
var_dump($restored);
Ожидаемый результат
string(1) "0"
int(0)

Вызов справа от = вычисляется первым, затем результат сохраняется в переменной слева. Кодирование вернуло строку; декодирование прочитало её и вернуло число. var_dump показывает типы, которые обычный echo визуально не различил бы. Здесь маленький заранее известный вход; работу с ошибками добавим отдельно.

Если вы ещё не работали с вложенными структурами, сначала пройдите JSON-текст → массив → чтение полей. Далее этот справочник раскрывает весь договор расширения, а не заменяет начальный урок сложным примером.

Какие значения можно передавать

В JSONПосле json_decodeПрикладной смысл
nullnullЗначение явно неизвестно или отсутствует по договору поля.
true / falseboolФлаг; не строки "true" и "false".
Числоint либо floatОчень большое целое может потерять точность без отдельного правила.
Строка в двойных кавычкахstring UTF-8Имя, код, телефон, дата; у JSON нет отдельного типа даты.
[элементы]array со спискомПоследовательность заказов.
{"имя": значение}stdClass либо array по associativeНабор именованных полей. JSON-объект не создаёт ваш класс Order.
Текст не определяет PHP-тип по внешнему виду
  1. JSON null → PHP null.
  2. JSON false → PHP bool false.
  3. JSON-строка "0041" → PHP string с сохранёнными нулями.
  4. JSON [4,1] → PHP array с двумя целыми значениями.
Корневое значение JSON не обязано быть объектомСамостоятельный пример
<?php
var_dump(json_decode('null'));
var_dump(json_decode('false'));
var_dump(json_decode('"0041"'));
var_dump(json_decode('[4, 1]'));
Ожидаемый результат
NULL
bool(false)
string(4) "0041"
array(2) {
  [0]=>
  int(4)
  [1]=>
  int(1)
}

Внешние одинарные кавычки относятся к PHP; внутренние двойные — к JSON. Для строки "0041" двойные кавычки являются частью переданного JSON-текста. JSON не поддерживает комментарии, одинарные кавычки вместо двойных, запятую после последнего элемента, NaN и Infinity.

Синтаксически верный документ ещё не заказ. Приложение отдельно требует объект, ключи, типы, диапазоны и доступ к данным. Повторяющиеся имена полей опасны при обмене между разными парсерами: PHP оставляет последнее значение. JSON-функции не дают встроенного режима «запретить дубликаты имён». Не проверяйте это регулярным выражением; для соответствующего протокола нужен парсер с такой политикой.

Установка, версии и точность чисел

В PHP 8 JSON является обязательным расширением и всегда включён. В более старых сборках его можно было отключить. json_encode/json_decode появились в PHP 5.2, json_last_error — 5.3, JsonSerializable — 5.4, текст ошибки — 5.5, JsonException и JSON_THROW_ON_ERROR — 7.3, json_validate — 8.3. Примеры последней функции требуют PHP 8.3+.

Проверка выполняемого окружения
  1. Текущий процесс PHP → его собственный список расширений.
  2. extension_loaded("json") → true: JSON доступен.
  3. function_exists("json_validate") → проверка конкретной функции, добавленной в 8.3.
  4. Результаты проверок относятся к этому процессу, не к соседнему веб-серверу.
Проверить расширение и более новую функциюСамостоятельный пример
<?php
var_dump(extension_loaded("json"));
var_dump(function_exists("json_validate"));
Ожидаемый результат
bool(true)
bool(true)

Ожидаемый результат относится к проверяемому PHP 8.5. На PHP 8.2 первая проверка истинна, вторая ложна. Если всё равно нужны данные, json_decode с обработкой ошибок подходит и без отдельного validate.

С PHP 7.1 формат float при кодировании зависит от serialize_precision; обычное значение −1 выбирает необходимое представление. Это не делает двоичные дроби точной десятичной арифметикой. Деньги передавайте целыми минимальными единицами или согласованной десятичной строкой. Большой ID лучше объявлять строкой ещё в API: JSON_BIGINT_AS_STRING защищает только целые числа при декодировании в PHP и не исправит точность, уже потерянную источником.

Две модели ошибки: результат или исключение

У json_encode без специальных флагов ошибка возвращает false; у json_decode — null. Но null бывает и правильным JSON-значением. В старом стиле сразу после вызова читают json_last_error. В новом коде удобно указать JSON_THROW_ON_ERROR и перехватить JsonException: успешный null тогда не смешивается с ошибкой разбора.

Где появляется ошибка и кто её обрабатывает
  1. json_decode($body, true, 16, JSON_THROW_ON_ERROR) начинает разбор.
  2. Текст повреждён → выбрасывается JsonException, присваивание $data не завершается.
  3. catch получает объект $error → код ошибки из getCode().
  4. Обработчик выбирает понятный отказ; ошибочный ответ не превращается в пустой заказ.
Корректный null и сломанный документ идут разными путямиСамостоятельный пример
<?php
foreach (['null', '{broken'] as $body) {
    try {
        $data = json_decode($body, true, 16, JSON_THROW_ON_ERROR);
        var_dump($data);
    } catch (JsonException $error) {
        echo "Документ не разобран\n";
        var_dump($error->getCode() === JSON_ERROR_SYNTAX);
    }
}
Ожидаемый результат
NULL
Документ не разобран
bool(true)

foreach по очереди подставляет два текста. try отмечает действие, в котором возможна ошибка; catch принимает исключение. getCode() — метод объекта ошибки, возвращающий её числовую категорию. Сравниваем её с именованной константой, а не с угаданной цифрой. Флаг объединяется с другими через |, а не через логическое ||.

У json_decode и json_validate значение depth вне допустимого диапазона даёт ValueError — это ошибка настройки вызова, а не испорченный документ. У json_encode поведение другое: превышение предела при обходе структуры относится к JSON_ERROR_DEPTH; скаляр вообще не требует такого обхода. Задавайте положительный предел и не рассчитывайте на общий для всех функций ValueError. Нарушение типа параметра может дать TypeError. Пользовательский jsonSerialize способен сам выбросить исключение; JSON_THROW_ON_ERROR не превращает все ошибки приложения в JsonException. Подробности try/catch и исключений нужны после первого понятного вызова, а не вместо него.

JsonException: что хранится в объекте ошибки

JsonException наследует Exception. Его создаёт JSON-операция с JSON_THROW_ON_ERROR при ошибке данных. Наследование здесь полезно: у разных ошибок общий способ получить сообщение, код, файл и цепочку причин. Приложение может обработать именно JSON-сбой, а выше по уровню — общий сбой импорта.

Часть ExceptionДля чего у JsonException
getCode()Категория JSON_ERROR_*; сравнивайте с константой.
getMessage()Текст для диагностики; не договор для ветвления и не обязательно готовое сообщение пользователю.
getFile(), getLine()Где выброшено исключение. Пути сервера не нужно показывать посетителю.
getTrace(), getTraceAsString()Стек вызовов как массив либо текст. В аргументах могут быть чувствительные данные.
getPrevious()Предыдущее исключение при передаче причины через конструктор.
__construct(message, code, previous)Позволяет создать объект ошибки; обычно JsonException создаёт сама JSON-функция.
__toString()Подробное текстовое представление для разработки; не публичный HTTP-ответ.
__clone()Закрыт: объекты исключений не предназначены для клонирования.

Служебные свойства message, code, file, line защищены, string, trace, previous закрыты. Читайте их указанными методами. Смысл этих областей видимости одинаков и в собственных классах.

Сохранить причину сбоя поставщика
  1. readSupplierPayload("{broken") → json_decode.
  2. Повреждённый документ → JsonException в $cause.
  3. Новый RuntimeException хранит понятное сообщение и previous=$cause.
  4. Внешний catch получает RuntimeException; getPrevious() возвращает исходный JsonException.
Добавить смысл задачи и сохранить исходную причинуСамостоятельный пример
<?php
function readSupplierPayload(string $body): mixed
{
    try {
        return json_decode($body, true, 32, JSON_THROW_ON_ERROR);
    } catch (JsonException $cause) {
        throw new RuntimeException("Поставщик вернул неверный JSON", 0, $cause);
    }
}
try {
    readSupplierPayload('{broken');
} catch (RuntimeException $error) {
    echo $error->getMessage(), "\n";
    var_dump($error->getPrevious() instanceof JsonException);
}
Ожидаемый результат
Поставщик вернул неверный JSON
bool(true)

Верхний уровень узнаёт, какая операция сорвалась, а диагностический код при необходимости читает исходный JsonException через getPrevious. Тело ответа и токены не добавляются в сообщение. instanceof проверяет принадлежность объекта классу. Сетевого запроса здесь нет: мы проверяем разбор уже полученного тела.

Флаги: выбирать по договору, а не включать все сразу

Флаг — именованное целое значение, включающее режим функции. Совместимые флаги объединяются побитовым |. Их номера не нужно запоминать или складывать вручную. У decode, encode и validate разные допустимые режимы.

Флаг / где применяетсяЧто меняет и когда нужен
JSON_OBJECT_AS_ARRAY / decodeСоздаёт массивы из JSON-объектов, если associative=null; явные true/false задают выбор прямо.
JSON_BIGINT_AS_STRING / decodeСохраняет целые за пределами int строками. Не защищает дроби/экспоненту и не заставляет все ID стать строками.
JSON_HEX_TAG / encodeПредставляет < и > через Unicode escape.
JSON_HEX_AMP / encodeПредставляет & через Unicode escape.
JSON_HEX_APOS / encodeПредставляет одинарную кавычку через Unicode escape.
JSON_HEX_QUOT / encodeПредставляет двойную кавычку внутри строк через Unicode escape.
JSON_FORCE_OBJECT / encodeПревращает PHP-списки, включая пустые, в JSON-объекты; действует рекурсивно. Для одного пустого объекта лучше явно создать (object) [].
JSON_NUMERIC_CHECK / encodeПревращает числовые строки в числа. Может испортить телефон, артикул, ведущие нули и точность ID; задавайте типы полей заранее.
JSON_PRETTY_PRINT / encodeДобавляет читаемые отступы и переводы строк; увеличивает размер документа.
JSON_UNESCAPED_SLASHES / encodeОставляет / без обратной косой черты. Смысл JSON-строки тот же.
JSON_UNESCAPED_UNICODE / encodeОставляет Unicode-буквы буквами, а не последовательностями \uXXXX. Это оформление текста, не исправление кодировки.
JSON_UNESCAPED_LINE_TERMINATORS / encode, PHP 7.1+Вместе с UNESCAPED_UNICODE оставляет U+2028/U+2029 неэкранированными. Не включайте ради абстрактного «очистить JSON».
JSON_PRESERVE_ZERO_FRACTION / encodeСохраняет .0 у float вроде 12.0. Не задаёт два знака после запятой и не решает денежную точность.
JSON_PARTIAL_OUTPUT_ON_ERROR / encodeРазрешает частичный результат с заменами неподдерживаемых значений. Имеет приоритет над THROW_ON_ERROR, поэтому может скрыть неполноту ответа.
JSON_INVALID_UTF8_IGNORE / encode, decode; validate / PHP 7.2+, validate 8.3+Пропускает некорректные UTF-8-байты. Данные меняются, а не становятся точным восстановлением исходного текста.
JSON_INVALID_UTF8_SUBSTITUTE / encode, decode / PHP 7.2+Заменяет неверные последовательности на U+FFFD. Подходит только при явно разрешённой потере данных; не принимается json_validate.
JSON_THROW_ON_ERROR / encode, decode / PHP 7.3+Бросает JsonException вместо записи кода ошибки в общее состояние. Не принимается json_validate.
Флаги задают оформление одного ответа
  1. Данные: name → Болт, path → /catalog/41.
  2. UNESCAPED_UNICODE оставляет буквы; UNESCAPED_SLASHES оставляет слеши.
  3. PRETTY_PRINT добавляет отступы; THROW задаёт путь ошибки.
  4. json_encode возвращает одну строку с теми же полями — флаги не отправляют её по сети.
Сделать локальный JSON удобнее для чтенияСамостоятельный пример
<?php
$data = ["name" => "Болт", "path" => "/catalog/41"];
echo json_encode($data, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
Ожидаемый результат
{
    "name": "Болт",
    "path": "/catalog/41"
}

Четыре режима собраны через |. Получился формат для просмотра человеком. Убирая PRETTY_PRINT, можно получить компактный текст с теми же данными. Не путайте визуально короткую запись со сжатием транспорта.

12.0 — float, но число печатается по-разномуСамостоятельный пример
<?php
echo json_encode(12.0), "\n";
echo json_encode(12.0, JSON_PRESERVE_ZERO_FRACTION);
Ожидаемый результат
12
12.0

Оба документа содержат JSON-число. Флаг сохраняет дробную форму float, но не обещает 12.00. Если внешний договор требует десятичную строку с двумя знаками, формируйте именно строковое поле по этому договору.

Автоматическое превращение всех числовых строк меняет кодСамостоятельный пример
<?php
$data = ["sku" => "0041", "quantity" => 2];
echo json_encode($data, JSON_THROW_ON_ERROR), "\n";
echo json_encode($data, JSON_THROW_ON_ERROR | JSON_NUMERIC_CHECK);
Ожидаемый результат
{"sku":"0041","quantity":2}
{"sku":41,"quantity":2}

Во втором ответе потеряны нули артикула. Правильный тип quantity уже int, ему флаг не нужен. Код товара и телефон должны оставаться строками, даже если состоят только из цифр.

Один объект задаём явно, не меняя вложенные спискиСамостоятельный пример
<?php
$data = ["filters" => (object) [], "items" => []];
echo json_encode($data, JSON_THROW_ON_ERROR), "\n";
echo json_encode($data, JSON_THROW_ON_ERROR | JSON_FORCE_OBJECT);
Ожидаемый результат
{"filters":{},"items":[]}
{"filters":{},"items":{}}

(object) [] создаёт пустой объект для одного поля. FORCE_OBJECT изменил и items, нарушив договор «массив товаров». Это видно ещё до реального HTTP-запроса.

Явная политика потери некорректных байтовСамостоятельный пример
<?php
$text = "A\xFFB";
echo json_encode($text, JSON_INVALID_UTF8_IGNORE), "\n";
echo json_encode($text, JSON_INVALID_UTF8_SUBSTITUTE);
Ожидаемый результат
"AB"
"A\ufffdB"

\xFF обозначает байт, который здесь не является допустимым UTF-8. IGNORE удалил его, SUBSTITUTE оставил знак замены. Оба варианта теряют исходное содержимое; для подписанного пакета, ID или финансовых данных молчаливое исправление обычно неприемлемо.

Частичный ответ может подавить ожидаемое исключениеСамостоятельный пример
<?php
$data = ["ratio" => INF];
echo json_encode($data, JSON_THROW_ON_ERROR | JSON_PARTIAL_OUTPUT_ON_ERROR), "\n";
var_dump(json_last_error() === JSON_ERROR_INF_OR_NAN);
Ожидаемый результат
{"ratio":0}
bool(true)

INF — бесконечность, у JSON такого числа нет. Частичный режим подставил 0, хотя математически это другое значение; исключение не выброшено. В передаче измерений лучше явно решить, означает ли ошибка отказ или отдельное поле null/status, и не скрывать её этим флагом.

Все категории JSON_ERROR_*

КонстантаЧто выяснить при таком результате
JSON_ERROR_NONEПоследняя учитываемая операция завершилась без ошибки.
JSON_ERROR_DEPTHВложенность превысила заданный предел. Это отличается от недопустимого параметра depth.
JSON_ERROR_STATE_MISMATCHНарушена структура вложенности/режим парсера, например неправильное закрытие контейнера.
JSON_ERROR_CTRL_CHARВнутри строки оказался недопустимый неэкранированный управляющий символ.
JSON_ERROR_SYNTAXJSON-синтаксис нарушен: одинарные кавычки, лишняя запятая, посторонний текст и другие случаи.
JSON_ERROR_UTF8Строковые данные не являются правильным UTF-8.
JSON_ERROR_RECURSIONПри encode найдена циклическая ссылка. PARTIAL заменяет проблемное место на null.
JSON_ERROR_INF_OR_NANВ encode попали INF/NAN. PARTIAL может заменить их на 0.
JSON_ERROR_UNSUPPORTED_TYPEВ encode попал неподдерживаемый тип, например ресурс. PARTIAL заменяет его на null.
JSON_ERROR_INVALID_PROPERTY_NAMEПри создании PHP-объекта имя свойства начинается с NUL. Декодирование в массив имеет другие ограничения ключей.
JSON_ERROR_UTF16В JSON escape встретился одиночный UTF-16 surrogate вместо корректной пары. Исходный транспорт по-прежнему должен быть UTF-8.
JSON_ERROR_NON_BACKED_ENUM / PHP 8.1+Обычный enum без backing value нельзя автоматически представить значением JSON. Явно выберите имя/поле или JsonSerializable.

Код ошибки полезен для машинного решения, текст — для диагностики. Не публикуйте весь документ, трассировку и токены в сообщении посетителю. Ошибка UTF-16 здесь относится к последовательности \uXXXX внутри JSON, а не к разрешению отправлять JSON-файл в UTF-16.

Код относится к конкретному неудачному разбору
  1. {"a":} → пропущено значение → JSON_ERROR_SYNTAX.
  2. Байт FF внутри строки → неверный UTF-8 → JSON_ERROR_UTF8.
  3. [[[1]]] при depth=2 → JSON_ERROR_DEPTH.
  4. Одиночный Unicode surrogate → JSON_ERROR_UTF16; после каждого опыта код читается сразу.
Различить повреждение синтаксиса, байтов и вложенностиСамостоятельный пример
<?php
$cases = [
    ['{"a":}', 16, JSON_ERROR_SYNTAX],
    ['"' . "\xFF" . '"', 16, JSON_ERROR_UTF8],
    ['[[[1]]]', 2, JSON_ERROR_DEPTH],
    ['"\uD800"', 16, JSON_ERROR_UTF16],
];
foreach ($cases as [$body, $depth, $expectedCode]) {
    json_decode($body, true, $depth);
    var_dump(json_last_error() === $expectedCode);
}
Ожидаемый результат
bool(true)
bool(true)
bool(true)
bool(true)

Внешний массив содержит отдельные опыты, каждый со своим ожидаемым кодом. Результат ошибки читается немедленно после decode, до любого другого JSON-вызова. [переменные] в foreach распаковывает три позиции строки примеров.

Как объект определяет публичное JSON-представление

Без специального договора json_encode берёт публичные свойства объекта. Если нужны другие имена полей, вычисленные значения или стабильный внешний формат, класс реализует интерфейс JsonSerializable. Интерфейс требует публичный метод jsonSerialize без параметров. Этот метод возвращает PHP-данные, которые затем кодирует json_encode.

Вложенный объект заказа
  1. json_encode(["order" => $order]) доходит до объекта.
  2. Объект реализует JsonSerializable → вызывается $order->jsonSerialize().
  3. Метод возвращает массив разрешённых полей, а не готовую JSON-строку.
  4. Кодировщик превращает этот массив в JSON внутри поля order.
  5. json_encode возвращает один итоговый текст вызывающему коду.

JSON-объект и PHP-объект класса — разные понятия. Для начала не нужен собственный класс: массив отлично подходит для простого ответа. Метод полезен, когда формат повторяется у многих экземпляров. JsonSerializable::jsonSerialize содержит минимальный класс, вложенный ответ и объяснение каждого шага.

Граница интеграции: синтаксис, схема и транспорт

Сначала проверьте статус HTTP, размер тела и ожидаемый Content-Type. Затем разбирайте JSON и проверяйте структуру данных. Успех HTTP не гарантирует полезный JSON, а верный JSON не гарантирует нужные поля. Ошибку авторизации в виде HTML не надо «исправлять», вырезая участок от первой фигурной скобки.

Адресное удаление известного префикса
  1. Входные байты: EF BB BF, затем {"stock":0}.
  2. str_starts_with проверяет ровно три начальных байта BOM.
  3. substr($body, 3) оставляет текст {"stock":0}.
  4. json_decode создаёт массив; чтение stock возвращает число 0.
Убрать ровно один известный BOM в согласованном формате импортаСамостоятельный пример
<?php
$body = "\xEF\xBB\xBF" . '{"stock":0}';
if (str_starts_with($body, "\xEF\xBB\xBF")) {
    $body = substr($body, 3);
}
$data = json_decode($body, true, 16, JSON_THROW_ON_ERROR);
echo $data['stock'];
Ожидаемый результат
0

Это адресная совместимость с известным экспортёром, который добавляет UTF-8 BOM. Удаляем точную последовательность только в начале. trim/ltrim с набором этих байтов — не удаление точного префикса. В обычном API предпочтительно исправить отправителя, а для подписи проверять исходные байты до нормализации по правилам протокола.

Не вызывайте stripslashes, html_entity_decode или «очистку всех управляющих» наугад: это меняет допустимые данные и способно сломать экранирование. Если источник прислал JSON внутри JSON-строки, нужно подтвердить такой договор, а не декодировать многократно до исчезновения ошибки. Диагностика реального ответа показывает дальнейший разбор.

Декодирование требует памяти для исходного текста и структуры; последующее encode создаёт ещё одну строку. Не загружайте огромный архив как одно тело без лимитов. Для больших потоков выбирайте согласованный построчный формат, пагинацию или специализированный потоковый парсер. JSON-функции из этой категории целиком обрабатывают переданное значение.

  • Нужно число из поля stock: decode с ошибкой, затем проверить объект/массив, наличие поля, int и допустимый диапазон.
  • Нужно только проверить JSON-файл перед хранением: validate подходит, но лимит размера и доверие к содержимому остаются отдельными.
  • После array_filter клиент видит объект вместо списка: если ключи технические, восстановить array_values; если это словарь, ключи сохранять.
  • После encode у телефона пропал + или нули: убрать NUMERIC_CHECK, проверить типы исходных полей.
  • Для повторяемого формата ответа объекта: JsonSerializable возвращает выбранный массив, json_encode вызывается один раз снаружи.

Все функции и интерфейс JSON

Функции и методы этой темы

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

json_last_errorПолучить числовую категорию последней JSON-операции, которая записывает общее состояние.

PHP 5.3+ · json

json_last_error(): int

Получить числовую категорию последней JSON-операции, которая записывает общее состояние.

Часть договораОбъяснение
ПараметрыОтсутствуют.
ВозвратJSON_ERROR_NONE либо одна из JSON_ERROR_*; код относится к последней учитываемой операции.
Область действияdecode/encode без действующего THROW и json_validate. THROW сам по себе состояние не обновляет; PARTIAL_OUTPUT_ON_ERROR имеет приоритет и может обновить его даже вместе с THROW.
Считать состояние до следующего вызова
  1. json_decode("null") → null; JSON_ERROR_NONE.
  2. json_decode("{broken") → null; JSON_ERROR_SYNTAX.
  3. Только код ошибки отличает два результата в режиме без исключений.
Одинаковый null имеет два разных объясненияСамостоятельный пример
<?php
$value = json_decode('null');
var_dump($value);
var_dump(json_last_error() === JSON_ERROR_NONE);
$value = json_decode('{broken');
var_dump($value);
var_dump(json_last_error() === JSON_ERROR_SYNTAX);
Ожидаемый результат
NULL
bool(true)
NULL
bool(true)

У json_last_error нет параметров: он читает общее состояние JSON-расширения. Сравнение с константой проверяет причину; сравнение результата decode с null само по себе недостаточно.

Сохранить код до следующего кодирования журналаСамостоятельный пример
<?php
json_decode('{broken');
$decodeError = json_last_error();
$logPayload = json_encode(["event" => "import_rejected"]);
var_dump(json_last_error() === JSON_ERROR_NONE);
var_dump($decodeError === JSON_ERROR_SYNTAX);
Ожидаемый результат
bool(true)
bool(true)

Успешный encode перезаписал глобальное состояние. Сохранённая переменная относится именно к decode. Пример только создаёт строку журнала в памяти, ничего не записывая.

Режим исключений не очищает старое состояниеСамостоятельный пример
<?php
json_decode('{broken');
json_decode('{}', true, 16, JSON_THROW_ON_ERROR);
var_dump(json_last_error() === JSON_ERROR_SYNTAX);
try {
    json_decode('[[[1]]]', true, 2, JSON_THROW_ON_ERROR);
} catch (JsonException $error) {
    var_dump($error->getCode() === JSON_ERROR_DEPTH);
}
var_dump(json_last_error() === JSON_ERROR_SYNTAX);
Ожидаемый результат
bool(true)
bool(true)
bool(true)

Вызовы с THROW не обновляют json_last_error. После них старый SYNTAX не описывает текущую операцию. В catch используйте $error->getCode(); не смешивайте две модели диагностики. Частичный encode — отдельный режим, описанный выше.

Рядом: json_last_error_msg, json_decode, json_encode. Полный список флагов и ошибок.

json_last_error_msgПолучить читаемое описание последней учитываемой JSON-ошибки.

PHP 5.5+ · json

json_last_error_msg(): string

Получить читаемое описание последней учитываемой JSON-ошибки.

Часть договораОбъяснение
ПараметрыОтсутствуют.
ВозвратОписание ошибки, при отсутствии — строка No error.
ОграничениеТа же модель общего состояния, что у json_last_error; после THROW читайте сообщение исключения.
Код для решения, текст для диагностической записи
  1. Неудачный json_decode записывает код и описание.
  2. json_last_error_msg() возвращает строку; сам не печатает.
  3. Сохранить текст до следующего JSON-вызова, показать человеку своё прикладное сообщение.
Показать диагностический текстСамостоятельный пример
<?php
json_decode('{broken');
echo json_last_error_msg(), "
";
json_decode('null');
echo json_last_error_msg();
Ожидаемый результат
Syntax error
No error

Строки показаны для проверяемого PHP. Для выбора действий сравнивайте JSON_ERROR_*: текст предназначен для чтения, а не устойчивого машинного договора.

Сохранить сообщение до формирования диагностического JSONСамостоятельный пример
<?php
$value = json_decode('{broken');
$code = json_last_error();
$message = json_last_error_msg();
if ($code !== JSON_ERROR_NONE) {
    $diagnostic = json_encode(["stage" => "supplier_decode", "message" => $message], JSON_THROW_ON_ERROR);
    echo $diagnostic;
}
Ожидаемый результат
{"stage":"supplier_decode","message":"Syntax error"}

В журнале выбран этап и текст ошибки; исходный ответ с возможными секретами не добавлен. Сообщение для посетителя можно сформулировать иначе: «Не удалось обновить остатки, попробуйте позже». Строка журнала здесь остаётся только демонстрационным выводом.

Рядом: json_last_error, json_decode, json_validate. Полный список флагов и ошибок.

Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.