嵌套字典与列表的键路径记录及跨JSON文件值同步实现问题求助
问题分析与解决方案
兄弟,我看了你的代码和问题,发现了几个关键问题,咱们一个个拆解解决:
首先,你代码里最直接的错误——你最后把修改后的目标JSON写到了源文件里,而不是目标文件!看你最后一段代码:
t_file = open(o_name + ".json", "w") t_file.write(json.dumps(t_json, indent=2, sort_keys=False))
这里o_name是源文件的名字"fu",所以你把修改后的t_json覆盖了源文件,而目标文件"bar.json"完全没被改动,这就是你觉得目标文件没变化的核心原因!
其次,你的key_list用了全局变量,递归过程中的pop时机非常混乱,导致路径有时候会出错。全局变量在递归场景下很容易出问题,咱们换个方式,把当前路径作为参数传递给递归函数,这样每个递归分支都有自己独立的路径,不会互相干扰。
最后,你定位目标JSON元素的逻辑可以简化,不需要区分dict和list,因为无论是字典的键还是列表的索引,都可以用entry[key]来访问和赋值。
修正后的完整代码
import json # 源文件和目标文件名 o_name = "fu" t_name = "bar" # 读取源JSON(用with语句自动管理文件关闭,更安全) with open(f"{o_name}.json", "r") as o_file: o_json = json.load(o_file) # 读取目标JSON with open(f"{t_name}.json", "r") as t_file: t_json = json.load(t_file) def nested_values_with_path(obj, current_path=None): """递归遍历嵌套结构,返回每个值及其对应的路径列表""" if current_path is None: current_path = [] if isinstance(obj, list): for index, value in enumerate(obj): new_path = current_path + [index] if isinstance(value, (list, dict)): yield from nested_values_with_path(value, new_path) else: yield (value, new_path) elif isinstance(obj, dict): for key, value in obj.items(): new_path = current_path + [key] if isinstance(value, (list, dict)): yield from nested_values_with_path(value, new_path) else: yield (value, new_path) else: # 理论上这里不会触发,因为上面已经处理了非嵌套类型 yield (obj, current_path) # 遍历源JSON的每个值和路径,同步到目标JSON for data, path in nested_values_with_path(o_json): print(f"路径: {path}, 值: {data}") # 定位到目标JSON的对应位置 entry = t_json for key in path[:-1]: entry = entry[key] # 直接赋值,无需区分dict和list entry[path[-1]] = data # 写入目标文件(这里要写t_name,不是o_name!) with open(f"{t_name}.json", "w") as t_file: json.dump(t_json, t_file, indent=2, sort_keys=False) print("同步完成!")
关键改动说明
- 修复文件保存错误:最后写入的是
t_name + ".json",也就是目标文件"bar.json",终于能正确保存修改后的内容了。 - 替换全局key_list为路径参数:
nested_values_with_path函数用current_path参数传递当前路径,每次递归时生成新的路径列表(new_path = current_path + [index/key]),避免了全局变量的副作用,路径逻辑清晰了很多。 - 简化目标元素定位逻辑:不再区分dict和list,直接通过路径逐层进入目标JSON的对应位置,然后赋值,代码更简洁。
- 使用with语句管理文件:比直接open/close更安全,能自动处理文件关闭,避免资源泄漏。
运行效果
运行后,你的目标文件bar.json会和源文件fu.json的内容完全一致,比如someList里的元素会被替换成源文件的内容,所有嵌套结构的差异值也会同步更新。
内容的提问来源于stack exchange,提问作者Loren Hickerson
相关产品推荐
相关产品推荐

