我的知识记录

Python嵌套JSON展开打平教程:扁平化嵌套字段

把深层嵌套的JSON数据用json_normalize或递归函数打平成扁平表,点号路径作为列名,方便转CSV和做分析,附完整代码。

场景痛点

接口返回的JSON一层套一层:user.profile.address.cityorder.items[0].sku,直接转CSV只能把嵌套字段塞成一坨字符串。想把 citysku 单独拉成列做筛选统计,就得先把嵌套结构"打平"。这篇用pandas的 json_normalize 和递归两种方式解决。

用到的库

pip install pandas

完整代码

# 嵌套JSON展开打平
import json
import pandas as pd

def flatten_with_json_normalize(json_path):
"""
用pandas自带的json_normalize,自动把嵌套dict展开成点号列名。
record_path 指定数组路径,meta 指定要带上的父级字段。
"""
with open(json_path, "r", encoding="utf-8") as f:
data = json.load(f)

# 情况1:根就是list[dict],直接打平
if isinstance(data, list):
df = pd.json_normalize(data)
else:
# 情况2:根是dict,里面有个数组需要展开
# 比如 {"orders": [{"user": {...}, "items": [...]}]}
# record_path 指向要展开的数组路径
df = pd.json_normalize(
data,
record_path="orders",          # 展开 orders 数组
meta=["user_id", "shop_id"],   # 把外层字段也带上
errors="ignore",
)

print("打平后列名:")
for c in df.columns:
print("  ", c)
print(f"\n形状:{df.shape}")
return df

def flatten_recursive(nested_dict, parent_key="", sep="."):
"""
递归手动打平,适定制灵活。
把 {"a": {"b": 1}} 变成 {"a.b": 1}
"""
items = {}
for k, v in nested_dict.items():
new_key = f"{parent_key}{sep}{k}" if parent_key else k
if isinstance(v, dict):
items.update(flatten_recursive(v, new_key, sep=sep))
elif isinstance(v, list):
# 列表类型:转成JSON字符串存着,或展开成多列
items[new_key] = json.dumps(v, ensure_ascii=False)
else:
items[new_key] = v
return items

def flatten_list_records(records):
"""对list[dict]批量递归打平。"""
flat = [flatten_recursive(r) for r in records]
return pd.DataFrame(flat)

def main():
json_file = "nested.json"

print("=== json_normalize 方式 ===")
df1 = flatten_with_json_normalize(json_file)
df1.to_csv("flatten_normalize.csv", index=False, encoding="utf-8-sig")

print("\n=== 递归方式(示例数据)===")
sample = [
{
"user": {"id": 1, "name": "张三", "address": {"city": "北京", "zip": "100000"}},
"order": {"id": 100, "amount": 299.5, "items": [{"sku": "A1"}, {"sku": "A2"}]},
},
{
"user": {"id": 2, "name": "李四", "address": {"city": "上海"}},
"order": {"id": 101, "amount": 599.0},
},
]
df2 = flatten_list_records(sample)
print(df2.T)
df2.to_csv("flatten_recursive.csv", index=False, encoding="utf-8-sig")

if __name__ == "__main__":
main()

代码讲解

  • pd.json_normalize(data) 是官方推荐,自动把嵌套dict展开成 user.address.city 这种点号列名。
  • record_path 指定哪个数组要"炸开",meta 指定哪些父级字段要平铺到每行。
  • 递归方式更灵活,遇到list就序列化成JSON字符串,遇到dict继续往下钻。
  • 打平后列名很长但清晰,df["user.address.city"] 直接取城市列。
  • 两种方式都输出CSV,打开就是扁平表格。

运行结果

控制台打印打平后的列名和表形状。当前目录生成两个CSV:flatten_normalize.csv 来自文件,flatten_recursive.csv 来自示例数据。嵌套字段全部变成顶层列,列表字段是JSON字符串。

注意事项

  • 数组里嵌套对象(比如 items: [{sku:1}, {sku:2}])不会自动拆成多行,要拆多行得先explode再normalise。
  • 列名带点号在pandas里访问用 df["user.address.city"],不要用属性访问 df.user.address
  • 超深嵌套(10层以上)列名会非常长,按需 rename 缩短关键列。
  • 递归方式遇到循环引用会爆栈,正常API数据不会有这问题。

Python嵌套JSON展开打平教程:扁平化嵌套字段

标签:

更新时间:2026-09-14 20:58:40

上一篇:Python处理异常值outliers检测与处理教程

下一篇:Python JSON转CSV教程:list[dict]一键导出表格