You need to enable JavaScript to run this app. Python将REST接口返回的多层嵌套JSON转换为细粒度DataFrame的方法
优惠活动
大模型
产品
解决方案
定价
更多

Python将REST接口返回的多层嵌套JSON转换为细粒度DataFrame的方法

多层嵌套广告JSON转最细粒度扁平DataFrame的实现方法

你之前用pd.json_normalize达不到预期效果,核心问题是没有顺着数据的嵌套结构逐层拆解“动态字典key”的结构——这个方法本身完全可以覆盖你的需求,不需要额外找复杂的第三方库,按下面的步骤操作就能拿到逐行对应最小数据单元的扁平表。

适配你的数据结构的固定拆解流程

你的原始JSON结构是三层嵌套动态字典 + 数组类指标,拆解的核心逻辑是:从最外层开始,把所有“字典key代表ID”的结构,全部转换成“ID值作为独立列”的长表结构,最后在最细粒度层拆分数组类指标,拿到最高数据粒度的逐行数据。

1. 拆解最外层campaign层级

你最外层是result节点下,以campaign_id为key的字典结构,直接用pd.DataFrame.from_dict会把campaign_id当成列名,完全不符合长表要求,先手动转成带campaignID列的基础表:

import pandas as pd
import json
import requests

# 你已经完成的请求逻辑
resp = requests.get("你的接口请求地址", headers={"自定义请求头"})
raw_data = json.loads(resp.text)

# 提取result节点下的campaign级数据
campaign_root = raw_data["result"]
# 转成带campaignID列的长表
campaign_base = pd.DataFrame([
    {"campaignID": camp_id, **camp_attr}
    for camp_id, camp_attr in campaign_root.items()
])

2. 拆解campaign下嵌套的creative层级

每个campaign对应的属性里,又嵌套了以creative_id为key的字典,沿着campaign表逐行拆:

  • 先把嵌套的creative字典列做explode拆成长形式
  • 再把每个creative字典的key转成creativeID独立列,同时保留上一层的campaign所有属性
# 提取campaign下行内嵌套的creative映射关系
campaign_base["creative_map"] = campaign_base["creatives"]
# 先把嵌套行拆平
creative_exploded = campaign_base.explode("creative_map")
# 把creative_id从字典key转成独立列,展开creative的基础属性
creative_base = pd.concat([
    creative_exploded.drop(columns=["creative_map", "creatives"]).reset_index(drop=True),
    pd.DataFrame([
        {"creativeID": cre_id, **cre_attr}
        for cre_id, cre_attr in creative_exploded["creative_map"].items()
    ])
], axis=1)

3. 拆解最细粒度的live统计层,含数组类指标

每个creative下嵌套的live_id为key的统计层,就是你要的最小粒度数据源,这一步用pd.json_normalize指定拆分数组的路径,直接拍平:

# 提取creative行内嵌套的live统计映射
creative_base["live_map"] = creative_base["live_stats"]
live_exploded = creative_base.explode("live_map")
# 先把live_id从字典key转成独立列
live_records = [
    {"liveID": live_id, **live_attr}
    for live_id, live_attr in live_exploded["live_map"].items()
]
# 用json_normalize拍平所有嵌套结构,拆分数组类指标到独立行
final_df = pd.json_normalize(
    data=live_records,
    # 填你结构里的数组类指标对应的key,比如分视频的统计数组名,没有数组的话传None
    record_path="video_metrics",
    # 指定要从上一层保留的所有列,包括你需要的campaignID、creativeID、device、liveID等
    meta=["liveID", "device", "campaignID", "creativeID", "其他需要保留的上层统计字段"],
    errors="ignore"
)

为什么之前的操作达不到效果

直接使用pd.json_normalize失败的常见原因:

  • 没有提前把“动态ID当字典key”的结构转成带ID列的记录形式,直接把最外层大字典整体传入,导致函数把动态ID当成顶层列名
  • 没有给record_path指定需要拆分成独立行的数组/嵌套层路径,导致所有嵌套结构被转成带点号的长列名,没有拆成逐行的最小粒度单元

零手写层级的懒人方案

如果不想逐层写拆解逻辑,可以用flatten_json工具递归展开所有嵌套字典:

from flatten_json import flatten
# 对拆到live层的所有记录做递归展开
flattened_records = [flatten(record) for record in live_records]
final_df = pd.DataFrame(flattened_records)
  • 这个工具会自动把嵌套路径用下划线拼接成扁平列名,遇到数组会自动把数组索引追加在列名后
  • 局限是不会自动把数组拆成独立行,展开后需要手动对数组类字段做explode才能拿到最高粒度的逐行数据

内容的提问来源于stack exchange,提问作者JCBoysenBerry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.03 03:45:08