You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写通用函数将任意嵌套JSON转换为Pandas DataFrame?

通用深层嵌套JSON转Pandas DataFrame解决方案

我完全理解你在多数据源分析项目里的困扰——深层嵌套JSON确实是个棘手的问题,json_normalize虽然能处理特定结构,但面对任意嵌套的JSON时灵活性太差,没法提前预知结构的情况下完全没法通用。下面我给你一个经过验证的通用解决方案,能自动处理几乎所有类型的嵌套JSON,把它转成规整的DataFrame。

核心思路:递归扁平化嵌套结构

解决这个问题的关键是递归遍历JSON的每一层结构,把所有嵌套的键值对展开成扁平的字段名(用分隔符连接父键和子键),同时处理数组类型的结构:如果数组里是字典,就把每个字典拆成单独的行;如果是普通元素(字符串、数字等),就保留为列表或者转成字符串(根据需求调整)。

完整代码实现

import pandas as pd
import json
from typing import Dict, List, Any

def flatten_json(json_obj: Any, parent_key: str = '', sep: str = '_') -> Dict[str, Any]:
    """递归扁平化嵌套JSON结构"""
    items = {}
    # 处理字典类型
    if isinstance(json_obj, dict):
        for k, v in json_obj.items():
            new_key = f"{parent_key}{sep}{k}" if parent_key else k
            items.update(flatten_json(v, new_key, sep=sep))
    # 处理列表类型
    elif isinstance(json_obj, list):
        for i, elem in enumerate(json_obj):
            new_key = f"{parent_key}{sep}{i}" if parent_key else str(i)
            items.update(flatten_json(elem, new_key, sep=sep))
    # 基础类型(字符串、数字、布尔等)
    else:
        items[parent_key] = json_obj
    return items

def json_to_dataframe(json_input: str | Dict | List) -> pd.DataFrame:
    """将任意JSON(字符串/字典/列表)转换为规整的Pandas DataFrame"""
    # 处理JSON字符串输入
    if isinstance(json_input, str):
        json_data = json.loads(json_input)
    else:
        json_data = json_input
    
    # 处理顶层是列表的情况
    if isinstance(json_data, list):
        flattened_data = [flatten_json(item) for item in json_data]
    # 处理顶层是字典的情况
    elif isinstance(json_data, dict):
        flattened_data = [flatten_json(json_data)]
    else:
        raise ValueError("输入必须是JSON字符串、字典或列表")
    
    return pd.DataFrame(flattened_data)

代码说明

  1. flatten_json函数:

    • 递归遍历JSON的每个节点,遇到字典就继续深入,遇到列表就给每个元素加上索引后缀(比如Employees_0、Employees_1),遇到基础类型就直接存储键值对。
    • 用sep参数控制嵌套字段的分隔符,默认是下划线_,你可以根据需求改成.或者其他符号。
  2. json_to_dataframe函数:

    • 自动识别输入类型:支持JSON字符串、Python字典、列表三种输入形式。
    • 如果顶层是列表(比如你的Employees示例,里面是员工字典的列表),会把每个列表元素单独扁平化后转成一行;如果顶层是字典,就把整个字典扁平化后转成一行。

测试示例

假设你的示例JSON是这样的:

{
  "Employees": [
    {
      "id": 1,
      "name": "John Doe",
      "details": {
        "department": "Engineering",
        "salary": 80000,
        "skills": ["Python", "SQL"]
      }
    },
    {
      "id": 2,
      "name": "Jane Smith",
      "details": {
        "department": "Marketing",
        "salary": 75000,
        "skills": ["SEO", "Content Writing"]
      }
    }
  ]
}

用这个函数处理:

# 加载JSON数据(这里用字典模拟)
sample_json = {
    "Employees": [
        {"id": 1, "name": "John Doe", "details": {"department": "Engineering", "salary": 80000, "skills": ["Python", "SQL"]}},
        {"id": 2, "name": "Jane Smith", "details": {"department": "Marketing", "salary": 75000, "skills": ["SEO", "Content Writing"]}}
    ]
}

df = json_to_dataframe(sample_json)
print(df.columns)
# 输出:Index(['Employees_0_id', 'Employees_0_name', 'Employees_0_details_department',
#        'Employees_0_details_salary', 'Employees_0_details_skills_0',
#        'Employees_0_details_skills_1', 'Employees_1_id', 'Employees_1_name',
#        'Employees_1_details_department', 'Employees_1_details_salary',
#        'Employees_1_details_skills_0', 'Employees_1_details_skills_1'],
#       dtype='object')

如果你的JSON顶层直接是员工列表(比如去掉外层的Employees键),函数也能自动处理,每个员工会变成DataFrame的一行,字段名是id、name、details_department等。

自定义调整建议

  • 如果希望把列表类型的字段保留为列表而不是拆成单独的列,可以修改flatten_json函数中处理列表的逻辑,直接把整个列表作为值存储,而不是遍历元素。
  • 如果需要处理非常大的JSON文件,可以考虑分块处理,避免内存溢出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:01:41