本文详解如何递归遍历多层嵌套的 json 树形结构(含容器、目录、文件),精准定位目标文件并生成包含容器名与完整层级路径的绝对路径,避免因起始节点错误导致路径截断。
本文详解如何递归遍历多层嵌套的 json 树形结构(含容器、目录、文件),精准定位目标文件并生成包含容器名与完整层级路径的绝对路径,避免因起始节点错误导致路径截断。
在处理类似文件系统结构的嵌套 JSON 数据时,一个常见误区是:将递归起点设为 children 数组而非容器根节点,从而丢失父目录名(如 'testdir'),导致路径不完整(如输出 testcontainer/test3.txt 而非 testcontainer/testdir/test3.txt)。
问题代码中关键错误在于:
container_data = jsonData['testcontainer'][0]['children'] # ❌ 错误:跳过了 'testdir' 这一层
这使得递归从 'testdir' 的子节点(即 children)开始,自然无法将 'testdir' 纳入路径。
✅ 正确做法是:从容器顶层条目(即 jsonData['testcontainer'])开始遍历,让递归函数自行处理 type='directory' 节点的命名与路径拼接。
以下是修复后的完整可运行教程代码:
jsonData = {
'01042014': [{'type': 'directory', 'name': 'Apr1', 'children': [{'type': 'directory', 'name': 'Apr2', 'children': [{'type': 'directory', 'name': 'Apr3', 'children': [{'type': 'file', 'name': 'inapr3.txt'}, {'type': 'file', 'name': 'test1.txt'}]}, {'type': 'file', 'name': 'inapr2.txt'}]}, {'type': 'file', 'name': 'inapr1.txt'}, {'type': 'file', 'name': 'test2.txt'}]}, {'type': 'file', 'name': 'inroot.txt'}, {'type': 'file', 'name': 'test1.txt'}],
'container0': [{'type': 'directory', 'name': 'dir0', 'children': [{'type': 'file', 'name': 'test0.txt'}]}],
'container1': [{'type': 'directory', 'name': 'dir1', 'children': [{'type': 'file', 'name': 'test1.txt'}]}],
'container2': [{'type': 'directory', 'name': 'dir2', 'children': [{'type': 'file', 'name': 'test2.txt'}]}],
'test1': [{'type': 'directory', 'name': 'testdir0', 'children': [{'type': 'file', 'name': 'test1.txt'}]}],
'test2': [{'type': 'directory', 'name': 'testdir', 'children': []}],
'testcontainer': [{'type': 'directory', 'name': 'testdir', 'children': [{'type': 'directory', 'name': 'Test10', 'children': []}, {'type': 'directory', 'name': 'testdir2', 'children': [{'type': 'directory', 'name': 'test3', 'children': [{'type': 'file', 'name': 'test3file.txt'}]}, {'type': 'file', 'name': 'test2file.txt'}]}, {'type': 'file', 'name': '2ndcopy.txt'}, {'type': 'file', 'name': 'test0.txt'}, {'type': 'file', 'name': 'test1.txt'}, {'type': 'file', 'name': 'test2.txt'}, {'type': 'file', 'name': 'test3.txt'}]}]
}
def find_file_path(data, filename, container='', current_path=''):
"""
递归查找文件并构建完整路径
Args:
data: 当前待遍历的数据(list of dict)
filename: 目标文件名(str)
container: 当前所属容器名(str)
current_path: 当前累积路径(不含容器前缀,如 '/testdir/testdir2')
Returns:
dict with keys 'container', 'filename', 'path' (full path including container), or None
"""
for item in data:
# 处理文件节点
if item.get('type') == 'file' and item.get('name') == filename:
full_path = f"/{container}{current_path}/{filename}"
return {
'container': container,
'filename': filename,
'path': full_path[1:] # 去掉开头的 '/'
}
# 处理目录节点:先加入当前目录名,再递归 children
elif item.get('type') == 'directory':
# 构建进入该目录后的新路径
new_path = f"{current_path}/{item['name']}"
# 递归搜索其 children
result = find_file_path(
item.get('children', []),
filename,
container,
new_path
)
if result:
return result
return None
# ✅ 正确调用方式:传入整个容器列表(如 jsonData['testcontainer'])
target_container = 'testcontainer'
filename = 'test3.txt'
# 注意:jsonData['testcontainer'] 是一个 list,可能含多个根目录项
container_entries = jsonData.get(target_container, [])
result = find_file_path(container_entries, filename, container=target_container)
if result:
print(result['path']) # 输出:testcontainer/testdir/test3.txt
else:
print(f"File '{filename}' not found in container '{target_container}'.")
? 关键要点总结:
- 路径构建时机:目录名应在进入该目录时(即 new_path = f"{current_path}/{item['name']}")加入路径,而非在匹配到文件时临时拼接;
- 容器传递一致性:container 参数需在每次递归中保持不变,确保最终路径包含正确的容器前缀;
- 健壮性增强:使用 .get() 防止 KeyError;支持容器内存在多个同名根目录项;
- 全局搜索扩展:若需跨所有容器搜索,只需外层遍历 jsonData.items() 并对每个 container_name, entries 调用 find_file_path。
通过以上修正,即可准确生成如 testcontainer/testdir/test3.txt 这类符合真实目录层级的完整路径,真正实现树形结构的深度优先精确定位。











