使用递归方法处理嵌套JSON数据:Python实现复杂结构的(完全扁平化)。

 一、引言

在数据处理过程中,嵌套的JSON结构往往给数据的解析和使用带来不少挑战。特别是当JSON对象中存在多层字典、列表,甚至嵌套的JSON字符串时,提取并将其转换为平面结构是一个常见且必要的需求。本文将介绍如何使用Python递归地展开嵌套JSON结构,使其转换为扁平化的键值对形式,便于后续的数据分析和处理。

二、解决方案:递归解析JSON

 1. 基本思路

我们使用递归的方式对JSON结构进行解析。如果遇到字典类型,我们会递归遍历其中的键值对;如果遇到列表类型,则对每个元素进行递归解析;如果遇到嵌套的JSON字符串,我们将尝试将其解析为字典并继续递归处理。

2. 核心代码

import json

def parse_data(data, prefix=''):
    results = []

    # 如果是字典,遍历每一个键值对
    if isinstance(data, dict):
        for key, value in data.items():
            full_key = f"{prefix}_{key}" if prefix else key  # 构建完整的键路径
            if isinstance(value, dict):  # 如果值是字典,递归解析
                results.extend(parse_data(value, full_key))
            elif isinstance(value, list):  # 如果值是列表,递归解析列表
                if value:
                    for index, item in enumerate(value):
                        list_prefix = f"{full_key}_{index}"
                        results.extend(parse_data(item, list_prefix))
                else:
                    results.append((full_key, value))
            elif isinstance(value, str):  # 如果是字符串,需要判断是否为json格式
                try:
                    # 尝试将字符串转换为字典(处理嵌套的json)
                    nested_dict = json.loads(value)
                    results.extend(parse_data(nested_dict, full_key))
                except json.JSONDecodeError:
                    results.append((full_key, value))  # 普通字符串直接添加
            else:
                # 处理字符串、数字、布尔类型等非嵌套数据
                results.append((full_key, value))

    # 直接返回非字典和非列表的数据
    elif isinstance(data, list):  # 如果是列表,单独处理
        for index, item in enumerate(data):
            list_prefix = f"{prefix}_{index}"
            results.extend(parse_data(item, list_prefix))
    else:
        # 处理基本数据类型(数字、字符串等)
        results.append((prefix, data))

    return results

3. 代码解读

  • 递归解析字典:当遇到字典类型时,递归遍历每一个键值对,并构造完整的键路径。
  • 处理列表:当值是列表时,对每一个元素进行递归解析,并在键名前增加索引。
  • 嵌套的JSON字符串:如果值是字符串类型,我们会尝试将其解析为字典,处理嵌套的JSON结构。
  • 结果存储:最终所有的键和值都会存储为键值对的列表,方便输出和使用。

三、测试用例

# 复杂示例
data1 = {
    "id": 1,
    "name": "Alice",
    "contact": {
        "email": "alice@example.com",
        "phone": "123-456-7890"
    },
    "orders": [
        {"order_id": 1001, "amount": 250},
        {"order_id": 1002, "amount": 450}
    ],
    "product": [
        {"product_id": 1,
         "product_contact": {
             "email": "product@example.com",
             "phone": "123-456-7890"
         }
         }
    ]
}

# 执行功能
test_data = parse_data(data1)
print("键值对:", (test_data))
print("转换成字典:", dict(test_data))


# 运行结果
键值对: [('id', 1), ('name', 'Alice'), ('contact_email', 'alice@example.com'), ('contact_phone', '123-456-7890'), ('orders_0_order_id', 1001), ('orders_0_amount', 250), ('orders_1_order_id', 1002), ('orders_1_amount', 450), ('product_0_product_id', 1), ('product_0_product_contact_email', 'product@example.com'), ('product_0_product_contact_phone', '123-456-7890')]

转换成字典: {'id': 1, 'name': 'Alice', 'contact_email': 'alice@example.com', 'contact_phone': '123-456-7890', 'orders_0_order_id': 1001, 'orders_0_amount': 250, 'orders_1_order_id': 1002, 'orders_1_amount': 450, 'product_0_product_id': 1, 'product_0_product_contact_email': 'product@example.com', 'product_0_product_contact_phone': '123-456-7890'}

# 简单的嵌套字典
data2 = {
    "name": "Alice",
    "details": {
        "age": 30,
        "address": {
            "city": "New York",
            "zip": "10001"
        }
    }
}
test_data = parse_data(data2)
print("键值对:", (test_data))
print("转换成字典:", dict(test_data)) 

 # 运行结果

键值对: [('name', 'Alice'), ('details_age', 30), ('details_address_city', 'New York'), ('details_address_zip', '10001')]
转换成字典: {'name': 'Alice', 'details_age': 30, 'details_address_city': 'New York', 'details_address_zip': '10001'}

# 列表嵌套
data3 = {
    "items": [
        {"product": "book", "price": 12.99},
        {"product": "pen", "price": 1.99}
    ]
}

# 执行函数
test_data = parse_data(data3)
print("键值对:", (test_data))
print("转换成字典:", dict(test_data))

# 运行结果

键值对: [('info_name', 'Bob'), ('info_location_city', 'San Francisco'), ('info_location_state', 'CA')]
转换成字典: {'info_name': 'Bob', 'info_location_city': 'San Francisco', 'info_location_state': 'CA'}
 

# 处理空列表
data4 = {
    "items": []
}

# 执行函数
test_data = parse_data(data4)
print("键值对:", (test_data))
print("转换成字典:", dict(test_data))

# 运行结果

键值对: [('items', [])]
转换成字典: {'items': []}

# 处理嵌套JSON字符串
data5 = {
    "info": '{"name": "Bob", "location": {"city": "San Francisco", "state": "CA"}}'
}

# 执行函数
test_data = parse_data(data5)
print("键值对:", (test_data))
print("转换成字典:", dict(test_data))

# 运行结果

键值对: [('info_name', 'Bob'), ('info_location_city', 'San Francisco'), ('info_location_state', 'CA')]
转换成字典: {'info_name': 'Bob', 'info_location_city': 'San Francisco', 'info_location_state': 'CA'}

# 多层嵌套
data6 = {
    "a": {
        "b": {
            "c": {
                "d": "final_value"
            }
        }
    }
}

# 执行函数
test_data = parse_data(data6)
print("键值对:", (test_data))
print("转换成字典:", dict(test_data))

 # 运行结果

键值对: [('a_b_c_d', 'final_value')]
转换成字典: {'a_b_c_d': 'final_value'}

四、总结

递归方法为我们提供了灵活且高效的方式来处理嵌套的JSON数据结构。无论是复杂的字典嵌套、列表,还是嵌套的JSON字符串,递归解析方法都能轻松应对。通过本文的代码示例和测试用例,相信大家能够轻松掌握处理嵌套JSON的技巧,并将其应用到实际的数据处理场景中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值