Python3/pandas≥1.1.4下用json_normalize如何保护嵌套对象不被扁平化
实现方案
你查阅官方文档找不到对应方案是正常的,截至目前pandas ≥1.1.4 版本的 json_normalize 仍未内置"嵌套字段保护"类参数,所有现有参数仅能调整扁平化的分隔符、列名前缀、错误处理规则,无法跳过指定嵌套对象的展开逻辑。
但完全可以通过两种无侵入的实现方式达到目标效果,兼容所有指定版本环境:
方案1:字段抽离回填(稳定性最高)
完全基于json_normalize的公开接口逻辑实现,不依赖任何内部实现细节,全版本兼容
- 执行逻辑:
- 遍历原始记录,将需要保护的
geometry完整嵌套对象从每条记录中抽出、单独存储为独立序列 - 移除原记录中的
geometry字段,对剩余结构执行默认的扁平化逻辑(此时properties等其他嵌套对象会按预期正常拆分) - 将抽出的完整
geometry对象作为独立列,拼回最终生成的DataFrame
- 遍历原始记录,将需要保护的
- 对应实现代码:
import json import pandas as pd # 原始API响应解析 res = ''' { "results": [ { "geometry": { "type": "Polygon", "crs": 4326, "coordinates": [[[6.0, 49.0],[6.0, 40.0],[7.0, 40.0],[7.0, 49.0],[6.0, 49.0]]] }, "attribute": "layer.metadata", "bbox": [6, 40, 7, 49], "featureName": "Coniferous_Trees", "layerName": "State_Forests", "type": "Feature", "id": "17", "properties": { "resolution": "100", "Year": "2020", "label": "Coniferous" } } ] } ''' raw_data = json.loads(res)['results'] protect_field = "geometry" # 1. 抽取待保护字段 protected_values = [] cleaned_data = [] for item in raw_data: protected_values.append(item[protect_field]) # 拷贝原记录,移除保护字段避免被拆分,不破坏原始数据结构 temp_item = item.copy() del temp_item[protect_field] cleaned_data.append(temp_item) # 2. 执行正常扁平化逻辑 df = pd.json_normalize(cleaned_data) # 3. 回填保护字段作为独立列 df[protect_field] = protected_values
- 效果验证:执行后输出的列结构完全匹配预期,
geometry列存储完整的原嵌套对象,无拆分:
print(df.columns.tolist()) # 输出: # ['attribute', 'bbox', 'featureName', 'layerName', 'type', 'id', # 'properties.resolution', 'properties.Year', 'properties.label', 'geometry']
方案2:非可拆分类包装(写法最简洁)
json_normalize的递归扁平化逻辑仅会展开字典、列表类型的嵌套值,遇到其他类型的实例时会直接作为单元格值保留,不会做拆分:
- 执行逻辑:
- 定义一个极简的标记类,用来包装需要保护的对象
- 遍历原始记录,将需要保护的
geometry字典替换成对应标记类的实例,直接执行原生json_normalize即可 - 后续如果需要获取原对象,直接从包装实例中取出原始内容即可
- 对应实现代码:
# 极简标记类,仅做类型区分用 class Protected: def __init__(self, raw_obj): self.value = raw_obj # 包装待保护的geometry字段 for item in raw_data: item["geometry"] = Protected(item["geometry"]) # 直接执行原生扁平化逻辑,无需额外清理 df = pd.json_normalize(raw_data) # 取出包装层,还原原对象 df["geometry"] = df["geometry"].apply(lambda x: x.value)
- 注意:这个方法利用了
json_normalize的内部类型判断逻辑,虽在≥1.1.4的所有pandas版本中可正常运行,但稳定性弱于方案1,适合快速开发场景使用。
内容的提问来源于stack exchange,提问作者swiss_knight
相关产品推荐
相关产品推荐

