Python 编程 递归函数 json_key_paths,用于遍历 JSON 对象(或类似 JSON 的对象,如字典和列表),并生成所有键的路径及其对应的值。
json
适用于现代 C++ 的 JSON。
项目地址:https://gitcode.com/gh_mirrors/js/json
免费下载资源
·
🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/
任务:编写一个递归函数来遍历 JSON 数据并获取所有 key 路径的组合。
具体实现:
- 为了达成这一需求,我们可以编写一个递归函数来遍历 JSON 数据的每个层级。该函数将利用
yield
关键字来逐个生成每个键的路径及其对应的值。 - 在处理过程中,我们将特别关注字典、列表和元组这三种数据类型,它们是构建 JSON 数据的基础。该函数首先会检查输入的 data 是否为字典、列表或元组。对于字典,函数将遍历每个键值对,并递归地调用自身来处理对应的值。若这些值属于基本数据类型,函数将生成包含当前完整路径和该值的元组。对于列表或元组,该函数将通过索引来标识每个元素的路径,并同样递归地处理每一个元素。
- 利用
yield
和yield from
语句,这种方法能高效处理大型 JSON 数据,它通过逐步生成每个结果,从而无需一次性将所有数据加载到内存中。
补充一个知识点,在 Python 编程语言中,基本数据类型包括以下几种:
- 整数 (int):表示整数值,例如
1
,-2
,100
。 - 浮点数 (float):表示小数值,例如
3.14
,-0.001
,1.0
。 - 布尔值 (bool):表示真或假,只有两个值
True
和False
。 - 字符串 (str):表示文本数据,例如
"Hello, World!"
,'Python'
。 - 列表 (list):有序的可变集合,例如
[1, 2, 3]
,['a', 'b', 'c']
。 - 元组 (tuple):有序的不可变集合,例如
(1, 2, 3)
,('a', 'b', 'c')
。 - 集合 (set):无序的唯一元素集合,例如
{1, 2, 3}
,{'a', 'b', 'c'}
。 - 字典 (dict):键值对的对应关系,例如
{'name': 'Alice', 'age': 25}
。 - 字节 (bytes):表示字节数据,例如
b'Hello'
,b'\x00\x01\x02'
。 - 字节数组 (bytearray):可变的字节数组,例如
bytearray(b'Hello')
。 - 复数 (complex):表示复数,例如
3 + 4j
,-1.5 + 2.3j
。 - NoneType (None):表示空值或缺失值,只有一个值
None
。
这些数据类型在 Python 中用于不同的数据处理和存储需求。
代码示例 1,基础版 Python 代码:
def json_key_paths(json_obj, parent_path=""):
"""
实现了一个递归函数 json_key_paths,用于遍历 JSON 对象并生成所有键的路径及其对应的值。
输入:
- json_obj:待遍历的 JSON 对象
- parent_path:当前路径的前缀,默认为空字符串。
输出:
- 键的路径及其对应的值
"""
if isinstance(json_obj, dict): # 检查 json_obj 是否为字典类型。如果是字典,则遍历其键值对。
for k, v in json_obj.items():
# 构建当前层的路径,如果 parent_path 不为空,则在其后添加键 k,否则直接使用键 k。
current_path = f"{parent_path}.{k}" if parent_path else k
# 如果值 v 是字典、列表或元组,递归调用 json_key_paths;否则,生成当前路径和值的元组。
if isinstance(v, (dict, list, tuple)):
yield from json_key_paths(v, current_path)
else:
# 如果是基本数据类型,则产生当前路径
yield current_path, v
elif isinstance(json_obj, (list, tuple)): # 检查 json_obj 是否为列表或元组类型。如果是列表或元组,遍历其元素。
for index_, v in enumerate(json_obj, start=0):
# 构建当前层的路径,使用索引 index_。
current_path = f"{parent_path}[{index_}]"
# 如果值 v 是字典、列表或元组,递归调用 json_key_paths;否则,生成当前路径和值的元组。
if isinstance(v, (dict, list, tuple)):
yield from json_key_paths(v, current_path)
else:
yield current_path, v
# 示例 JSON 数据
json_example = {
"name": "John",
"age": 30,
"languages": ["English", "French"],
"address": {"street": "1234 Elm St", "city": "Somewhere"},
"cars": {
"Nissan": ["Altima", "Leaf", "Maxima"],
"Ford": {"Sedan": "Fiesta", "Truck": "F-150", "SUV": "Explorer"},
},
"isActive": True,
}
json_example = {
"company": {
"name": "Tech Innovations",
"address": {
"street": "123 Tech Lane",
"city": "Innovation City",
"state": "Tech State",
"zip": "12345",
"country": "Techland",
"coordinates": {
"latitude": "40.7128",
"longitude": "-74.0060",
"mapLink": "https://maps.google.com/?q=40.7128,-74.0060",
},
},
"departments": {
"engineering": {
"manager": "John Doe",
"employees": {"employee1": "Jane Smith", "employee2": "Bob Johnson"},
},
"marketing": {
"manager": "Alice Brown",
"employees": {"employee1": "Charlie Davis", "employee2": "Diana Evans"},
},
"sales": {
"manager": "Eva Ford",
"employees": {
"employee1": "George Gibson",
"employee2": "Helen Harris",
},
},
},
"projects": {
"project1": {
"name": "AI Development",
"description": "Developing advanced AI algorithms",
"team": {
"lead": "Ivy Irwin",
"members": {"member1": "Jack Jackson", "member2": "Katie King"},
},
},
"project2": {
"name": "Cloud Solutions",
"description": "Building scalable cloud infrastructure",
"team": {
"lead": "Liam Lee",
"members": {"member1": "Mia Martin", "member2": "Noah Nelson"},
},
},
},
}
}
# 实际上是生成包含当前完整路径和值的元组
# for tuple_ in json_key_paths(json_example):
# print(tuple_)
for path, value in json_key_paths(json_example):
print(f"{path} -> {value}")
这段代码实现了一个递归函数 json_key_paths
,用于遍历 JSON 对象(字典、列表或元组)并生成所有键的路径及其对应的值。具体来说,它解决了以下问题:
- 遍历复杂结构:JSON 对象可能包含嵌套的字典、列表或元组,这个函数能够递归地遍历这些结构。
- 生成路径:对于每个键值对,生成从根节点到当前键的路径,路径格式为字符串,便于后续处理。
- 处理嵌套结构:对于嵌套的字典、列表或元组,递归调用自身,确保所有层级的键值对都能被遍历到。
结果如下:
实际上,上面的 Python 代码具有进一步优化的潜力。通过利用 collections.abc
模块中的 Mapping
和 Sequence
,我们可以简化类型检查的过程。
collections.abc
模块是 Python 的容器抽象基类。这些抽象基类可用于判断一个具体类是否具有特定的接口,如是否可哈希或是否为映射类。Mapping
:只读且可变的映射的抽象基类;Sequence
:只读且可变的序列的抽象基类。抽象基类的应用:
- 确定类和示例是否拥有特定函数,如判断对象是否可迭代、是否有键值对、是否可哈希等。
- 可用作混入类,简化类的开发。
- 如实现 Set API 的类只需提供 __contains__、__iter__ 和 __len__ 方法。
代码示例 2,进阶版 Python 代码:
# 从 collections.abc 导入 Mapping 和 Sequence,用于类型检查。
from collections.abc import Mapping, Sequence
def json_key_paths(json_obj, parent_path=""):
# 定义 base_data_type 元组,包含基本数据类型,用于排除这些类型以避免递归。
base_data_type = (int, float, str, bool, bytes, complex, type(None))
# 如果 json_obj 算是 Mapping 类型,遍历其键值对。
if isinstance(json_obj, Mapping):
for k, v in json_obj.items():
# 构建当前路径 current_path,如果 parent_path 不为空,则使用字符串拼接来连接路径和键。
current_path = f"{parent_path}.{k}" if parent_path else k
# 如果值 v 是 Mapping 或 Sequence,且不是基本数据类型,递归调用 json_key_paths。
if isinstance(v, (Mapping, Sequence)) and not isinstance(v, base_data_type):
yield from json_key_paths(v, current_path)
# 否则,生成当前路径和值。
else:
yield current_path, v
# 如果 json_obj 是 Sequence 且不是基本数据类型,遍历其元素。
elif isinstance(json_obj, Sequence) and not isinstance(json_obj, base_data_type):
for index_, v in enumerate(json_obj):
# 构建当前路径 current_path,使用字符串拼接来连接路径和索引。
current_path = f"{parent_path}[{index_}]"
# 如果值 v 是 Mapping 或 Sequence,且不是基本数据类型,递归调用 json_key_paths。
if isinstance(v, (Mapping, Sequence)) and not isinstance(v, base_data_type):
yield from json_key_paths(v, current_path)
# 否则,生成当前路径和值。
else:
yield current_path, v
json_example = {
"company": {
"name": "Tech Innovations",
"address": {
"street": "123 Tech Lane",
"city": "Innovation City",
"state": "Tech State",
"zip": "12345",
"country": "Techland",
"coordinates": {
"latitude": "40.7128",
"longitude": "-74.0060",
"mapLink": "https://maps.google.com/?q=40.7128,-74.0060",
},
},
"departments": {
"engineering": {
"manager": "John Doe",
"employees": {"employee1": "Jane Smith", "employee2": "Bob Johnson"},
},
"marketing": {
"manager": "Alice Brown",
"employees": {"employee1": "Charlie Davis", "employee2": "Diana Evans"},
},
"sales": {
"manager": "Eva Ford",
"employees": {
"employee1": "George Gibson",
"employee2": "Helen Harris",
},
},
},
"projects": {
"project1": {
"name": "AI Development",
"description": "Developing advanced AI algorithms",
"team": {
"lead": "Ivy Irwin",
"members": {"member1": "Jack Jackson", "member2": "Katie King"},
},
},
"project2": {
"name": "Cloud Solutions",
"description": "Building scalable cloud infrastructure",
"team": {
"lead": "Liam Lee",
"members": {"member1": "Mia Martin", "member2": "Noah Nelson"},
},
},
},
}
}
for path, value in json_key_paths(json_example):
print(f"{path} -> {value}")
结果如下:
GitHub 加速计划 / js / json
18
5
下载
适用于现代 C++ 的 JSON。
最近提交(Master分支:2 个月前 )
960b763e
5 个月前
8c391e04
8 个月前
更多推荐
已为社区贡献16条内容
所有评论(0)