Pandas处理非固定结构嵌套JSON创建DataFrame问题咨询
pandas 不规则嵌套JSON拆分为多列方案
问题说明
- 需将接口返回的JSON响应在pandas中拆分到不同列,直接使用
pd.json_normalize无法正确拆分嵌套对象,多次尝试其他方案均未达到预期 - 待处理JSON结构不固定,存在三类数据形态:
- 包含
financeInfo字段 - 不包含
financeInfo字段 - 仅存在
financeInfoAttributes字段、无financeInfo字段
- 包含
- 待处理JSON样例如下:
{ "codeId": "fc-5599", "financeInfo": [ { "date": "2022-01-30", "totalReturn": 0.022425456852 }, { "date": "2022-01-30", "totalReturn": 0.022425456852 }, { "date": "2022-01-30", "totalReturn": 0.022425456852 }, { "date": "2022-01-30", "totalReturn": 0.022425456852 }, { "date": "2022-01-30", "totalReturn": 0.022425456852 }, { "date": "2022-02-28", "totalReturn": -0.0424735070051586, "financeInfoAttributes": [ { "attributeId": "a-256", "value": "12.032791372796499" }, { "attributeId": "a-257", "value": "9.975964795996589" }, { "attributeId": "a-258", "value": "4.719852927810759" }, { "attributeId": "a-259", "value": "4.18144793134823" } ] } ] }
- 原有实现采用多次
pd.merge关联拆分后的表,核心代码如下:
normalizedfinanceInfo = pd.json_normalize(financeInfo[0], max_level=1) financeInfoAndfinanceInfoAttributes = pd.merge(normalizedfinanceInfo , financeInfoAttributes, left_index=True, right_index=True, how='outer') result = pd.merge(codeId, financeInfoAndfinanceInfoAttributes , left_index=True, right_index=True, how='left') final_result = pd.DataFrame(result)
该方案流程冗余,且存在索引对齐错误、字段匹配异常问题,输出结果不符合预期。
实现方案
直接利用pd.json_normalize的路径配置参数处理两层嵌套结构,搭配空值自动忽略逻辑适配不固定的JSON结构,无需多次手动merge。
完整代码
import pandas as pd import numpy as np # raw_data 替换为接口返回的JSON解析结果(即response.json()返回值) raw_data = {} # 此处替换为实际输入数据 # 前置判断:无financeInfo字段时直接生成仅含codeId的结果 if 'financeInfo' not in raw_data: final_result = pd.json_normalize(raw_data) else: # 第一步:展开顶层字段与financeInfo数组,自动忽略不存在的字段 df_finance = pd.json_normalize( raw_data, record_path='financeInfo', meta=['codeId'], errors='ignore' ) # 第二步:处理financeInfo下嵌套的financeInfoAttributes数组 if 'financeInfoAttributes' in df_finance.columns: # 展开属性数组,保留关联主键 df_attr = pd.json_normalize( df_finance.to_dict('records'), record_path='financeInfoAttributes', meta=['codeId', 'date', 'totalReturn'], errors='ignore' ) # 将属性键值对透视成独立列 df_attr_pivot = df_attr.pivot( index=['codeId', 'date', 'totalReturn'], columns='attributeId', values='value' ).reset_index() # 合并属性列与财务主表,缺失值自动填充NaN final_result = df_finance.drop(columns=['financeInfoAttributes']).merge( df_attr_pivot, on=['codeId', 'date', 'totalReturn'], how='left' ) else: final_result = df_finance # 可选:将属性列转换为数值类型 attr_cols = [col for col in final_result.columns if str(col).startswith('a-')] final_result[attr_cols] = final_result[attr_cols].astype(np.float64)
关键逻辑说明
errors='ignore'参数:自动跳过当前数据中不存在的字段,不会抛出KeyError,适配三类结构不固定的输入数据- 分层展开逻辑:分别对两层数组结构调用
json_normalize,通过meta参数保留关联主键,避免索引错位 - 透视转换:将长格式的属性键值对转换为宽表列,和财务数据行自动对齐
- 边界适配:针对无
financeInfo、无financeInfoAttributes的场景做了分支处理,不需要额外修改逻辑即可兼容所有输入形态
内容的提问来源于stack exchange,提问作者user8422715
相关产品推荐
相关产品推荐

