无需指定层级路径,如何扁平化任意嵌套JSON并提取所有child数据
提取所有嵌套层级
child数组数据到DataFrame的解决方案 问题描述
有层级不固定的嵌套JSON结构,需要提取所有层级child数组中的type、key、id、value字段到DataFrame。尝试使用pd.json_normalize指定固定多层record_path时,出现child列NaN和空列表的问题,无法完整获取数据。
JSON结构
└─ (array) └─ (object) ├─ "site" (string) ├─ "title" (string) ├─ "child" (array) │ └─ (object) │ ├─ "type" (string) │ ├─ "value" (string) │ ├─ "child" (array) │ │ └─ (object) │ │ ├─ "type" (string) │ │ ├─ "value" (string) │ │ ├─ "child" (array) │ │ │ └─ (object) │ │ │ ├─ "type" (string) │ │ │ ├─ "key" (string) │ │ │ ├─ "id" (string) │ │ │ └─ "value" (string) │ │ ├─ "id" (string) │ │ └─ "key" (string) │ ├─ "id" (string) │ └─ "key" (string) ├─ "featured_image_url" (string) ├─ "id" (string) └─ "key" (string)
示例数据
data = [{"site": "example", "title": "Example Site", "child": [{"type": "text", "value": "This is some text.", "child": [{"type": "image", "value": "image.jpg", "child": [{"type": "link", "key": "link1", "id": "link1", "value": "Link 1"}], "id": "text1", "key": "text1"}, {"type": "image", "value": "image2.jpg", "child": [{"type": "link", "key": "link2", "id": "link2", "value": "Link 2"}], "id": "text2", "key": "text2"}], "id": "root", "key": "root"}, {"featured_image_url": "featured_image.jpg", "id": "root2", "key": "root2"}]}]
失败的尝试
df = pd.json_normalize(data, record_path=['child', 'child', 'child'], meta=['site', 'title', 'featured_image_url', 'id', 'key','child'], meta_prefix='_')
执行后df.child列出现NaN和空列表,无法完整获取所有层级数据。
解决方案
由于JSON嵌套层级不固定,pd.json_normalize无法适配动态层级提取,采用递归遍历的方式收集所有child节点数据:
1. 编写递归收集函数
import pandas as pd def collect_child_items(item, parent_metadata=None): # 存储当前节点数据 item_data = { 'type': item.get('type'), 'key': item.get('key'), 'id': item.get('id'), 'value': item.get('value') } # 合并父级元数据(如顶层的site、title等) if parent_metadata: item_data.update(parent_metadata) results = [item_data] # 递归处理当前节点的child数组 if 'child' in item and isinstance(item['child'], list): for child in item['child']: results.extend(collect_child_items(child, parent_metadata)) return results # 提取顶层元数据 top_level_meta = {} all_child_records = [] for top_item in data: # 保存顶层的全局元数据 top_level_meta = { 'site': top_item.get('site'), 'title': top_item.get('title'), 'featured_image_url': top_item.get('featured_image_url'), 'root_id': top_item.get('id'), 'root_key': top_item.get('key') } # 遍历顶层的child数组,开始递归收集 if 'child' in top_item and isinstance(top_item['child'], list): for child in top_item['child']: all_child_records.extend(collect_child_items(child, top_level_meta)) # 转换为DataFrame final_df = pd.DataFrame(all_child_records)
2. 结果说明
运行后得到的final_df会包含:
- 所有层级
child节点的type、key、id、value字段 - 顶层元数据(site、title等),方便关联每个子节点所属的顶层数据
- 无NaN或遗漏的节点,完整覆盖所有嵌套层级
自定义调整
可以根据需求修改item_data中的字段,添加或移除需要提取的键;如果不需要顶层元数据,只需去掉parent_metadata相关的合并逻辑即可。
内容的提问来源于stack exchange,提问作者RustyShackleford
相关产品推荐
相关产品推荐

