2026, Jan 08 21:02
Как исправить AttributeError: 'list' object has no attribute 'items' при разборе JSON в Python
Почему возникает AttributeError: 'list' object has no attribute 'items' при работе с JSON в Python и как правильно итерировать список под ключом и пары словаря.
Разбирать JSON просто, пока форма данных соответствует ожиданиям вашего цикла. Частая ошибка — принимать список за словарь. Вот короткий пример: вы пытаетесь перебирать пары ключ–значение из JSON‑файла и сразу получаете AttributeError: 'list' object has no attribute 'items'.
Структура данных
В JSON‑файле есть ключ, который указывает на список, внутри которого лежит один словарь. Именно это различие — список вместо словаря — и вызывает ошибку.
{
"offer": [
{"bleach": 14 ,
"tshirt": 25,
"notebook": 6,
"mayo": 3,
"kiwi": 11,
"perfume": 68,
"hat": 2,
"toy": 17}
]
}
Проблемный код
Этот фрагмент считает, что по ключу лежит словарь, и сразу вызывает items(). Логика верная, но тип контейнера — нет.
import json
with open("offers.json", "r") as fh:
offers_block = json.load(fh)["offer"]
for idx, (k, v) in enumerate(offers_block.items()):
print(f"{str(idx + 1)} {k} {v:02} $")
Почему возникает ошибка
Ключ offer ссылается на список, а не на словарь. У списков нет метода items(), поэтому его вызов приводит к AttributeError. Чтобы получить пары ключ–значение, сначала пройдитесь по списку, а затем работайте с каждым словарём внутри.
Правильный подход
Итерируйте список под offer, убедитесь, что каждый элемент — словарь, и затем перечисляйте его пары. Так сохраняется логика и явно задаются типы контейнеров.
import json
with open("offers.json") as fp:
payload = json.load(fp)
for entry in payload.get("offer", []):
assert isinstance(entry, dict)
for n, (name, amount) in enumerate(entry.items(), 1):
print(f"{n} {name} ${amount}")
Почему это важно
При разборе JSON структура определяет логику обхода. Если по ключу лежит список — его нужно итерировать. Если словарь — работать через items(). Путаница между ними приводит к ошибкам выполнения, которые легко упустить. Безопасный доступ через get со значением по умолчанию помогает избежать KeyError, если ключа нет. Простая проверка типа проясняет ожидания и делает цикл надёжным, когда данные именно такие, какими вы их считаете.
Выводы
Прежде чем писать циклы, проверьте, является ли узел в JSON‑дереве списком или словарём, и стройте обход соответственно. Сначала проходите списки, затем при необходимости переходите к элементам словаря через items(). Небольшие страховки — значение по умолчанию в get и явная проверка типа — экономят время и делают намерения кода однозначными.