如何不使用pandas将嵌套JSON转换为结构正确的有序列
嵌套JSON扁平化处理问题
问题描述
处理嵌套JSON结构做扁平化转表格时,原有对象遍历结合pandas生成DataFrame的方案输出结构不符合预期,尝试脱离pandas直接生成固定有序列的方案未得到目标结果,需要可落地的代码优化思路。
测试样例数据
{ "financeCodeId": "fc-5599", "financeData": [ { "date": "2022-01-30", "calcTotalReturn": 0.022425456852 }, { "date": "2022-01-30", "calcTotalReturn": 0.022425456852 }, { "date": "2022-01-30", "calcTotalReturn": 0.022425456852 }, { "date": "2022-01-30", "calcTotalReturn": 0.022425456852 }, { "date": "2022-01-30", "calcTotalReturn": 0.022425456852 }, { "date": "2022-02-28", "calcTotalReturn": -0.0424735070051586, "financeDataAttributes": [ { "attributeId": "a-256", "value": "12.032791372796499" }, { "attributeId": "a-257", "value": "9.975964795996589" }, { "attributeId": "a-258", "value": "4.719852927810759" }, { "attributeId": "a-259", "value": "4.18144793134823" } ] } ] }
注:原样例JSON存在括号缺失的语法问题,已补全修正。
原有问题代码
items = [] for i in response_finance['results']: items.append(i.get('financeCodeId')) for j in i['financeData']: if 'financeDataAttributes' not in j: items.append({j.get('date'), j.get('calcTotalReturn')}) else: for k in j['financeDataAttributes']: items.append({k.get('attributeId'), k.get('value')}) df = pd.DataFrame.from_records(items) flat = pd.json_normalize(json.loads(df.to_json(orient="records")))
效果对比
- 实际错误输出:

- 预期正确输出:

优化方案
原有代码问题
- 存入
items列表的数据类型混杂,同时包含字符串、集合两种结构,pandas解析时无法对齐字段,直接导致列错位。 - 没有做层级关联:外层
financeCodeId、中层日期/收益率、内层属性值被拆成了独立条目,没有按行绑定归属关系。 - 存在冗余逻辑:生成DataFrame后再转JSON再做
json_normalize,多余的序列化/反序列化步骤容易引入格式问题。
修正后代码
核心思路是按行构造完整记录,每一行从最外层字段开始逐层绑定所有关联字段,动态属性直接展开为列名,最后一次性转DataFrame自动对齐列:
import pandas as pd rows = [] for res_item in response_finance['results']: # 取最外层公共字段 base_info = {"financeCodeId": res_item.get("financeCodeId")} # 遍历中层financeData条目 for finance_item in res_item["financeData"]: current_row = base_info.copy() current_row["date"] = finance_item.get("date") current_row["calcTotalReturn"] = finance_item.get("calcTotalReturn") # 无属性的条目直接存入 if "financeDataAttributes" not in finance_item: rows.append(current_row) continue # 有属性的条目,把每个attributeId作为列名,对应value作为列值 for attr in finance_item["financeDataAttributes"]: current_row[attr.get("attributeId")] = attr.get("value") rows.append(current_row) # 生成最终DataFrame,缺失字段自动填充空值 df = pd.DataFrame(rows) # 如果需要固定列顺序,手动指定列序列即可 # df = df[["financeCodeId", "date", "calcTotalReturn", "a-256", "a-257", "a-258", "a-259"]]
如果需要完全不依赖pandas生成有序列结构,只需要先遍历全量数据收集所有出现过的attributeId作为固定列头,再按相同的行构造逻辑逐行写入即可,核心关联逻辑和上述代码一致。
内容的提问来源于stack exchange,提问作者user8422715
相关产品推荐
相关产品推荐

