Avatar ·

Ошибка "Cannot use object of type stdClass as array" при работе с JSON в PHP

Всем привет! Я новичок в PHP и столкнулся со странной ошибкой, которую не могу понять. Пишу скрипт, который получает данные от API в формате JSON, декодирует их и пытается вывести в цикле. Вот мой код: ```php $json = file_get_contents('https://api.example.com/users'); $data = json_decode($json); foreach ($data as $user) { echo $user['name'] . '
'; echo $user['email'] . '
'; } ``` Но при запуске получаю: **Fatal error: Cannot use object of type stdClass as array**. Я думал, что json_decode() возвращает массив, но, видимо, это не так. Что я делаю не так? Как правильно обращаться к данным после декодирования JSON? В интернете нашел много обсуждений, но конкретного решения для моего случая не понял. Буду благодарен за подробное объяснение с примерами! P.S. Если я делаю var_dump($data), то вижу что-то вроде: `object(stdClass)#1 (2) { ["name"]=> string(4) "John" ["email"]=> string(15) "john@example.com" }`. Значит, это объект, а не массив. Как мне с ним работать? <<>>

Причина ошибки

Функция json_decode() по умолчанию возвращает объекты типа stdClass, а не массивы. Когда вы пытаетесь обратиться к свойству объекта через синтаксис массива $user['name'], PHP выдает фатальную ошибку, потому что объект нельзя использовать как массив.

Решение №1: Использовать синтаксис объекта

Самый простой способ — обращаться к свойствам через стрелку ->:


$json = file_get_contents('https://api.example.com/users');
$data = json_decode($json);

foreach ($data as $user) {
    echo $user->name . '<br>';
    echo $user->email . '<br>';
}

Теперь $user — это объект stdClass, и мы получаем его свойства через $user->name.

Решение №2: Преобразовать JSON в ассоциативный массив

Если вам удобнее работать с массивами, передайте второй параметр true в json_decode():


$data = json_decode($json, true); // true = ассоциативный массив

foreach ($data as $user) {
    echo $user['name'] . '<br>';
    echo $user['email'] . '<br>';
}

Теперь $data и все вложенные элементы будут массивами, и исходный код заработает без изменений.

Решение №3: Проверка типа данных

Если вы не уверены, что получите на выходе, используйте is_array() или is_object() для проверки:


$data = json_decode($json);

if (is_object($data)) {
    echo $data->name;
} elseif (is_array($data)) {
    echo $data['name'];
}

Дополнительные советы

  • Вложенные структуры: если JSON содержит объекты внутри массивов, рекурсивно применяйте тот же принцип. Например: $users[0]->address->city или $users[0]['address']['city'] (если используете true).
  • Обработка ошибок: всегда проверяйте, что json_decode() не вернул null (некорректный JSON): if ($data === null) { die('Ошибка парсинга JSON'); }.
  • Рекурсивное преобразование: если нужно гарантированно получить массив любой глубины, напишите рекурсивную функцию или используйте json_decode($json, true) — это автоматически преобразует все уровни.

Почему так происходит?

PHP по умолчанию представляет JSON-объекты {} как stdClass, а JSON-массивы [] — как обычные PHP-массивы. Это логично, так как объекты и массивы в JSON имеют разную семантику. Второй параметр true заставляет игнорировать эту разницу и всё превращать в массивы — это удобно для быстрой разработки, но может быть неочевидно для новичков.

Выберите тот подход, который вам ближе. Лично я рекомендую использовать true для простых скриптов и синтаксис объектов для более сложных проектов с ООП.

<<>>

Альтернативный подход: приведение типов и работа с stdClass

Если вы не хотите менять код глобально, можно преобразовать объект в массив "на лету" с помощью приведения типа (array):


$json = file_get_contents('https://api.example.com/users');
$data = json_decode($json);

foreach ($data as $user) {
    $user = (array) $user; // преобразуем объект в массив
    echo $user['name'] . '<br>';
    echo $user['email'] . '<br>';
}

Это работает, но есть нюансы:

  • Приведение типа (array) преобразует только первый уровень. Вложенные объекты останутся объектами.
  • Для глубокого преобразования нужна рекурсивная функция:

function objectToArray($data) {
    if (is_object($data)) {
        $data = (array) $data;
    }
    if (is_array($data)) {
        foreach ($data as $key => $value) {
            $data[$key] = objectToArray($value);
        }
    }
    return $data;
}

$data = objectToArray(json_decode($json));

Также можно использовать встроенную функцию json_decode($json, true) — она делает то же самое, но эффективнее. Поэтому данный способ рекомендую только для случаев, когда нужно частичное преобразование или когда вы работаете с уже существующим объектом stdClass.