
本文介绍使用 pandas.json_normalize 配合元数据(meta)机制,高效、安全地从多层嵌套 api 返回的 json 中,按 type 字段条件筛选并提取对应 prices.decimal 数值的方法。
本文介绍使用 pandas.json_normalize 配合元数据(meta)机制,高效、安全地从多层嵌套 api 返回的 json 中,按 type 字段条件筛选并提取对应 prices.decimal 数值的方法。
在处理真实世界 API 返回的嵌套 JSON 数据时,常见需求是:仅当某上级字段(如 "type": "MR")满足条件时,才提取其子级中 "prices" 数组内的 "decimal" 值。直接用循环遍历 + 多次 json_normalize(如原代码中在 for 循环内对 match_result 再次 normalize)不仅逻辑混乱、性能低下,更会因数据结构错位导致 KeyError 或空结果——因为 match_result 是一维 Series,而 prices 实际嵌套在原始 JSON 的更深路径中,无法被它直接作为 record_path 源。
正确做法是一次性展开至目标层级,并将判断条件字段作为元数据保留。以本例为例,目标路径为 data → events → markets → outcomes → prices,而判断依据 type 位于 data.events.markets.outcomes 层。此时应:
- 将 record_path 设为完整价格路径 ['data', 'events', 'markets', 'outcomes', 'prices'];
- 将 type 字段通过 meta 参数向上逐级指定其完整路径:[['data', 'events', 'markets', 'outcomes', 'type']];
- 利用 pandas 的布尔索引快速筛选。
完整可运行代码如下:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
import pandas as pd
import requests as r
api = 'https://content.toto.nl/content-service/api/v1/q/event-list?startTimeFrom=2024-03-31T22%3A00%3A00Z&startTimeTo=2024-04-01T21%3A59%3A59Z&started=false&maxMarkets=10&orderMarketsBy=displayOrder&marketSortsIncluded=--%2CCS%2CDC%2CDN%2CHH%2CHL%2CMH%2CMR%2CWH&marketGroupTypesIncluded=CUSTOM_GROUP%2CDOUBLE_CHANCE%2CDRAW_NO_BET%2CMATCH_RESULT%2CMATCH_WINNER%2CMONEYLINE%2CROLLING_SPREAD%2CROLLING_TOTAL%2CSTATIC_SPREAD%2CSTATIC_TOTAL&eventSortsIncluded=MTCH&includeChildMarkets=true&prioritisePrimaryMarkets=true&includeCommentary=true&includeMedia=true&drilldownTagIds=691&excludeDrilldownTagIds=7291%2C7294%2C7300%2C7303%2C7306'
response = r.get(api)
data = response.json()
# ✅ 一步展开:以 prices 为记录单元,同时携带 type 作为元数据列
df = pd.json_normalize(
data,
record_path=['data', 'events', 'markets', 'outcomes', 'prices'],
meta=[['data', 'events', 'markets', 'outcomes', 'type']]
)
# ? 筛选 type == 'MR' 对应的所有 decimal 值(返回 Series)
meta_col = 'data.events.markets.outcomes.type'
mr_decimals = df.loc[df[meta_col] == 'MR', 'decimal'].reset_index(drop=True)
print("MR 类型对应的 decimal 值:")
print(mr_decimals.tolist())
⚠️ 注意事项:
- meta 中路径必须与 record_path 的“父级”结构严格匹配,否则会报 KeyError 或填充 None;
- 若 JSON 中存在缺失字段(如某些 outcomes 下无 prices),json_normalize 默认跳过该分支,确保结果健壮;
- 使用 df[meta_col].eq('MR') 比 == 更推荐(尤其处理含 NaN 的列),但本例中 type 为必填字段,二者等效;
- 如需进一步关联赛事名称、时间等信息,可将更多字段加入 meta 列表,例如 [['data', 'events', 'name'], ['data', 'events', 'startTime']]。
该方法避免了手动循环与重复解析,兼具可读性、性能与可维护性,是处理深层条件查询 JSON 的标准实践。










