
本文详解如何处理含多层嵌套列表的json响应(如英国电网api),避免因误将列表当字典访问导致的typeerror,并提供健壮、可复用的字段提取方法。
本文详解如何处理含多层嵌套列表的json响应(如英国电网api),避免因误将列表当字典访问导致的typeerror,并提供健壮、可复用的字段提取方法。
在调用类似英国国家电网实时发电数据API时,返回的JSON结构常包含多层嵌套的列表(list)与字典(dict)混合结构。初学者容易忽略这一点,直接使用字符串键(如 "fuel")索引列表,从而触发 TypeError: list indices must be integers, not str —— 这正是你遇到的核心问题。
观察你的原始输出:
{
"data": [
{
"dnoregion": "England",
"data": [
{
"generationmix": [
{"fuel": "biomass", "perc": 8.8},
{"fuel": "coal", "perc": 0},
...
]
}
]
}
]
}
可见:
- grid_data["data"] 是列表(含1个区域对象);
- grid_data["data"][0]["data"] 是另一个列表(含1个时段数据);
- grid_data["data"][0]["data"][0]["generationmix"] 才是燃料类型列表;
- 每个燃料项是字典,需遍历匹配 "fuel": "coal",再取 "perc" 值。
✅ 正确做法如下(增强健壮性):
import requests
import json
response = requests.get(grid_url)
response.raise_for_status() # 自动抛出HTTP错误(如404/500)
grid_data = response.json() # 推荐用 .json() 替代 json.loads(response.text)
# 安全提取:逐层检查是否存在 + 使用列表推导或循环
try:
regions = grid_data.get("data", [])
if not regions:
raise ValueError("No region data found in response")
first_region = regions[0]
time_slots = first_region.get("data", [])
if not time_slots:
raise ValueError("No time-slot data found in region")
latest_slot = time_slots[0]
generation_mix = latest_slot.get("generationmix", [])
# 方式1:遍历查找(推荐,逻辑清晰)
coal_entry = None
for item in generation_mix:
if item.get("fuel") == "coal":
coal_entry = item
break
if coal_entry:
coal_percentage = coal_entry["perc"]
print(f"Coal contribution: {coal_percentage}%")
else:
print("Coal data not available in generation mix")
except (KeyError, IndexError, TypeError, ValueError) as e:
print(f"Data extraction failed: {e}")
⚠️ 注意事项:
- 永远不要假设嵌套结构存在:使用 .get(key, default) 或 try/except 防御性编程;
- 列表索引需校验长度:regions[0] 前先确认 len(regions) > 0;
- 避免硬编码索引:若需最新时段,优先按 to 时间排序后再取,而非固定 [0];
- 区分 response.json() 与 json.loads(response.text):前者自动处理编码与异常,更安全。
总结:JSON解析的关键在于「先看结构,再写路径」。建议用 JSONLint 格式化响应体,或在Python中用 pprint.pprint(grid_data) 可视化层级;一旦识别出列表位置,就用整数索引+循环/条件筛选替代直接键访问——这是处理真实世界API数据的必备技能。











