Python解析API返回单键嵌套JSON为字典并转DataFrame
问题根因
之前的解析方案存在三个典型错误:
- 错误使用
ndjson处理返回结果:该接口返回标准单块JSON,ndjson仅适用于换行分隔的多段JSON流,场景完全错配 - 归一化时未定位到实际数据路径:直接对顶层返回对象做
json_normalize,只会拿到唯一顶层键drugMemberGroup,无法触达内部嵌套的药品数组 - 重复
json.loads/json.dumps操作不会改变JSON的嵌套结构,无法解决路径定位错误的核心问题
处理步骤
1. 基础请求与JSON加载
不要做多余的格式转换,urllib3返回的响应是bytes类型,直接解码为UTF-8字符串后单次加载即可:
import urllib3 import json import pandas as pd from pandas import json_normalize # 初始化连接池 http = urllib3.PoolManager() req_url = "https://rxnav.nlm.nih.gov/REST/rxclass/classMembers.json?classId=C&relaSource=ATC&trans=0" resp = http.request("GET", req_url) # 单次加载JSON,不要重复做dumps/loads操作 resp_data = json.loads(resp.data.decode("utf-8"))
2. 定位目标数据数组
接口返回的326条药品记录实际存储在drugMemberGroup.drugMember路径下,先提取该数组做校验:
# 提取药品记录数组 drug_records = resp_data["drugMemberGroup"]["drugMember"] # 校验长度,正常返回326 print(f"获取到药品记录数:{len(drug_records)}")
3. 转换为可操作字典
如果需要扁平化的字典列表,直接遍历提取字段即可,把minConcept下的核心字段提升到外层,保留nodeAttr属性数组:
formatted_drug_dict = [] for record in drug_records: # 提取minConcept下的rxcui、药品名称、tty字段 drug_base = record["minConcept"].copy() # 保留属性数组和其他顶层字段 drug_base["nodeAttr"] = record.get("nodeAttr", []) for key, val in record.items(): if key not in ["minConcept", "nodeAttr"]: drug_base[key] = val formatted_drug_dict.append(drug_base)
4. 转换为规整pandas DataFrame
根据是否需要展开nodeAttr属性数组,选择对应方案:
方案A:不展开属性数组,保留为列值
直接使用json_normalize展平minConcept嵌套结构,nodeAttr以数组形式存在列中:
df = json_normalize( drug_records, meta=["nodeAttr"], record_prefix="drug_" ) # 重命名列更易读 df = df.rename(columns={ "drug_rxcui": "rxcui", "drug_name": "drug_name", "drug_tty": "tty" })
方案B:展开属性数组为规整长表
如果需要把nodeAttr中存储的药品属性(如ATC编码、定义等)展平为单独列,做二次归一化即可:
# 先展平第一层嵌套 df = json_normalize(drug_records) # 清理列名 df.columns = [col.replace("minConcept.", "") for col in df.columns] # 炸开nodeAttr数组 df = df.explode("nodeAttr").reset_index(drop=True) # 展平nodeAttr内的属性字段 attr_cols = json_normalize(df["nodeAttr"]).add_prefix("attr_") # 拼接得到最终宽表 df = pd.concat([df.drop(columns=["nodeAttr"]), attr_cols], axis=1)
常见报错排查
KeyError: 'drugMember':先打印resp_data.keys()检查返回结构,通常是请求参数传错(如classId、relaSource拼写错误)导致接口返回错误响应- 类型报错
list indices must be integers or slices, not str:检查取值路径,不要跳过drugMemberGroup层级直接取drugMember - JSON解析报错:确认响应状态码为200,不要对异常响应(如404、500的HTML页面)做JSON加载
内容的提问来源于stack exchange,提问作者user1470034
相关产品推荐
相关产品推荐

