Декодирование JSON в PHP с помощью json_decode: подробный разбор

Раздел: Обработка данных -> Декодирование JSON

Декодирование JSON в PHP: функция json_decode

Наиболее эффективный способ декодирования JSON в PHP

Использование функции json_decode() с флагом JSON_THROW_ON_ERROR (доступно с PHP 7.3). Этот подход позволяет обрабатывать ошибки декодирования через исключения, что упрощает контроль потока выполнения и делает код чище.


$json = '{"name":"Иван","age":30}';
try {
    $data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
    echo "Данные получены: ";
    print_r($data);
} catch (JsonException $e) {
    echo "Ошибка декодирования JSON: " . $e->getMessage();
}
  

Php json decode (php: json_decode() - декодирование json)

Данные получены: Array ( [name] => Иван [age] => 30 )
  

Типичные проблемы и их решения:

  • Некорректная кодировка: JSON должен быть в UTF-8. Для очистки используйте флаги JSON_INVALID_UTF8_IGNORE или JSON_INVALID_UTF8_SUBSTITUTE.
  • Слишком большая глубина вложенности: увеличьте параметр depth (по умолчанию 512).
  • Большие целые числа теряют точность: применяйте флаг JSON_BIGINT_AS_STRING.
  • Синтаксические ошибки в JSON: проверяйте строку на лишние запятые, неэкранированные кавычки, неправильные типы кавычек (только двойные).

Как декодировать JSON строку в ассоциативный массив?

Передайте второй аргумент true для получения ассоциативного массива вместо объекта stdClass.


$json = '{"city":"Москва","year":2023}';
$result = json_decode($json, true);
print_r($result);
  
Array ( [city] => Москва [year] => 2023 )
  

Если флаг не указан, по умолчанию возвращается объект stdClass. Ошибка может возникнуть, если в JSON встречаются ключи, недопустимые для свойств объекта (например, начинающиеся с цифры). Решение: всегда указывайте true для работы с массивами.

Как обработать некорректный JSON без исключений?

Проверьте возвращаемое значение на null и используйте json_last_error() для получения кода ошибки.


$json = '{invalid}';
$data = json_decode($json);
if ($data === null && json_last_error() !== JSON_ERROR_NONE) {
    echo 'Ошибка: ' . json_last_error_msg();
} else {
    print_r($data);
}
  
Ошибка: Syntax error
  

Важно разделять случай, когда JSON содержит строку "null" (корректное значение) и ошибку декодирования. Проверка $data === null может быть ложной, если JSON равен "null". Дополнительно проверяйте json_last_error().

Как декодировать с сохранением больших целых чисел?

Большие числа (больше PHP_INT_MAX) теряют точность при преобразовании в int. Используйте флаг JSON_BIGINT_AS_STRING.


$json = '{"big":123456789012345678901234567890}';
$data = json_decode($json, true, 512, JSON_BIGINT_AS_STRING);
echo $data['big']; // выводится как строка
  
123456789012345678901234567890
  

Без флага число будет округлено до float, что приведёт к потере точности. Решение: всегда применяйте JSON_BIGINT_AS_STRING при работе с потенциально большими числами.

Как ограничить глубину декодирования?

Третий параметр depth задаёт максимальную глубину вложенности (по умолчанию 512).


$json = '{"a":{"b":{"c":1}}}';
$data = json_decode($json, true, 2); // глубина 2
var_dump($data);
  
NULL (из-за превышения глубины)
  

При недостаточной глубине функция возвращает null. Решение: увеличивайте глубину или проверяйте ошибку JSON_ERROR_DEPTH.

Как декодировать JSON с управляющими символами или некорректной кодировкой?

Используйте флаги JSON_INVALID_UTF8_IGNORE (пропустить) или JSON_INVALID_UTF8_SUBSTITUTE (заменить на символ U+FFFD).


$json = "{\"text\":\"\xc3\x28\"}"; // некорректный UTF-8
$data = json_decode($json, true, 512, JSON_INVALID_UTF8_SUBSTITUTE);
echo $data['text'];
  
� (заменяющий символ)
  

Без флага декодирование вернёт null с ошибкой JSON_ERROR_UTF8. Решение: предварительно очищайте строку или используйте флаги.

Как проверить, является ли строка валидным JSON, без полного декодирования?

Можно вызвать json_decode() с флагом JSON_THROW_ON_ERROR и перехватить исключение, или проверить json_last_error(). Но полное декодирование всё равно происходит. Эффективный способ - парсить через json_decode и проверять ошибку.


function isValidJson($string) {
    json_decode($string);
    return json_last_error() === JSON_ERROR_NONE;
}
var_dump(isValidJson('{"valid":true}'));
var_dump(isValidJson('not json'));
  
bool(true)
bool(false)
  

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

Расширенные примеры работы с json_decode

Пример 1: Декодирование сложной вложенной структуры с различными флагами

Показано использование нескольких флагов одновременно: JSON_THROW_ON_ERROR, JSON_BIGINT_AS_STRING и JSON_OBJECT_AS_ARRAY (эквивалент второго параметра true).

Пример

$json = '{
  "id": 12345678901234567890,
  "user": {
    "name": "Алексей",
    "attributes": [1, 2, 3]
  }
}';

try {
    $data = json_decode($json, true, 512, JSON_THROW_ON_ERROR | JSON_BIGINT_AS_STRING);
    echo "ID: " . $data['id'] . " (тип: " . gettype($data['id']) . ")\n";
    print_r($data['user']);
} catch (JsonException $e) {
    echo "Ошибка: " . $e->getMessage();
}
  
ID: 12345678901234567890 (тип: string)
Array
(
    [name] => Алексей
    [attributes] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
        )
)
  

Обратите внимание, что id сохранился как строка благодаря JSON_BIGINT_AS_STRING. Без флага он превратился бы в float с потерей точности.

Пример 2: Рекурсивное преобразование stdClass в массив

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

Пример

function objectToArray($data) {
    if (is_object($data)) {
        $data = get_object_vars($data);
    }
    if (is_array($data)) {
        return array_map(__FUNCTION__, $data);
    }
    return $data;
}

$json = '{"a":{"b":[1,2,{"c":3}]}}';
$obj = json_decode($json);
$arr = objectToArray($obj);
print_r($arr);
  
Array
(
    [a] => Array
        (
            [b] => Array
                (
                    [0] => 1
                    [1] => 2
                    [2] => Array
                        (
                            [c] => 3
                        )
                )

        )

)
  

Функция get_object_vars работает только для public свойств. Если объект содержит private или protected свойства, они не будут включены. Для stdClass это безопасно.

Пример 3: Декодирование JSONP (JSON с callback)

Иногда внешние API возвращают JSONP: callback({...}). Необходимо удалить вызов функции и скобки, затем декодировать внутренний JSON.

Пример

$jsonp = 'myFunction({"result":"ok","count":42})';
preg_match('/\((.*)\)$/', $jsonp, $matches);
if (isset($matches[1])) {
    $json = $matches[1];
    $data = json_decode($json, true);
    print_r($data);
} else {
    echo "Неверный формат JSONP";
}
  
Array
(
    [result] => ok
    [count] => 42
)
  

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

Пример 4: Обработка BOM (Byte Order Mark) в JSON строке

Файлы JSON могут содержать BOM в начале (например, UTF-8 BOM: \xEF\xBB\xBF). Необходимо удалить его перед декодированием.

Пример

$jsonWithBom = "\xEF\xBB\xBF{\"key\":\"value\"}";
$json = ltrim($jsonWithBom, "\xEF\xBB\xBF");
$data = json_decode($json, true);
print_r($data);
  
Array ( [key] => value )
  

Без удаления BOM функция json_decode вернёт null с ошибкой синтаксиса. Решение: всегда проверяйте и удаляйте BOM, особенно при чтении из файлов.

Пример 5: Декодирование с проверкой типов полученных данных

Иногда требуется убедиться, что определённое поле имеет ожидаемый тип (например, число, а не строка). Используйте is_int, is_string и т.д.

Пример

$json = '{"age":"25"}';
$data = json_decode($json, true);

if (isset($data['age'])) {
    // Принудительное преобразование, если нужно число
    $age = (int)$data['age'];
    echo $age; // 25
}
  
25
  

Исходное значение "25" - строка. Если приложение ожидает целое число, может потребоваться явное приведение. Для строгих проверок используйте filter_var($data['age'], FILTER_VALIDATE_INT).

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

Можно создать функцию-обёртку, которая логирует все ошибки декодирования.

Пример

function safeJsonDecode($json, $assoc = false, $depth = 512, $flags = 0) {
    $result = json_decode($json, $assoc, $depth, $flags);
    if (json_last_error() !== JSON_ERROR_NONE) {
        error_log('JSON decode error: ' . json_last_error_msg() . ' for input: ' . substr($json, 0, 100));
        return null;
    }
    return $result;
}

$data = safeJsonDecode('{"valid":true}');
var_dump($data);
  
object(stdClass)#1 (1) { ["valid"]=> bool(true) }
  

Обёртка не выбрасывает исключения, а логирует ошибку и возвращает null. Это удобно для пакетной обработки, когда нужно продолжить выполнение.

PHP: json_decode() - декодирование JSON - comments

En
Php json decode (php)