Python中如何重命名JSON加载的字典键并保持顺序?
问题:修改JSON加载的字典键名并保持顺序
我有一个存储应用数据的JSON文件,结构为外层字典,每个键对应包含text、directory等字段的嵌套字典。读取文件赋值给buttons_data后,需要完成两个操作:
- 修改指定外层键下的嵌套值(例如把"Survival"对应的
text改为"Survival Mods") - 将该外层键名修改为与新的
text值一致,同时保持字典原有顺序
我编写了rename_key函数,对脚本内手动定义的同结构字典有效,但对JSON加载的字典无效,即便二者结构完全一致。相关JSON结构和代码如下:
示例JSON结构
{ "Survival": { "text": "Survival", "directory": "C:\\Users\\Famille Arcand\\Downloads\\Mods\\Survival\\", "fg_color": "#1e69a4", "hover_color": "#144870" }, "Creative": { "text": "Creative", "directory": "C:\\Users\\Famille Arcand\\Downloads\\Mods\\Creative\\", "fg_color": "#1e69a4", "hover_color": "#144870" }, "Redstone": { "text": "Redstone", "directory": "C:\\Users\\Famille Arcand\\Downloads\\Mods\\Redstone\\", "fg_color": "#1e69a4", "hover_color": "#144870" }, "Create": { "text": "Create", "directory": "C:\\Users\\Famille Arcand\\Downloads\\Mods\\Create\\", "fg_color": "#1e69a4", "hover_color": "#144870" }, "1.21": { "text": "1.21", "directory": "C:\\Users\\Famille Arcand\\Downloads\\Mods\\1.21\\", "fg_color": "#1e69a4", "hover_color": "#144870" }, "Ice Boat": { "text": "Ice Boat", "directory": "C:\\Users\\Famille Arcand\\Downloads\\Mods\\Ice Boat\\", "fg_color": "#1e69a4", "hover_color": "#144870" }, "Mods Lohan": { "text": "Mods Lohan", "directory": "C:\\Users\\Famille Arcand\\Downloads\\Mods\\Mods Lohan\\", "fg_color": "#1e69a4", "hover_color": "#144870" } }
现有Python代码
def rename_key(d, old_key, new_key): return {new_key if k == old_key else k: v for k, v in d.items()} with open(buttons, 'r') as json_file: buttons_data = json.load(json_file) for button in list(buttons_data.keys()): if button == text: buttons_data[button]["text"] = new_text buttons_data[button]["directory"] = new_directory buttons_data[button]["fg_color"] = new_fg_color buttons_data[button]["hover_color"] = new_hover_color rename_key(buttons_data, text, new_text) break
解决方案
问题根源
你的rename_key函数确实能生成修改键名后的新字典,但没有将返回的新字典赋值回buttons_data,导致原字典完全没被修改。另外,若要严格保证顺序,需注意Python版本对字典有序性的支持。
方法1:适配Python3.7+(默认字典有序)
直接修正现有逻辑,将rename_key的返回值赋值给buttons_data,同时补全写回JSON文件的步骤:
def rename_key(d, old_key, new_key): return {new_key if k == old_key else k: v for k, v in d.items()} # 定义要修改的参数 text = "Survival" new_text = "Survival Mods" new_directory = "C:\\Users\\Famille Arcand\\Downloads\\Mods\\Survival Mods\\" new_fg_color = "#1e69a4" new_hover_color = "#144870" # 读取JSON文件 with open(buttons, 'r') as json_file: buttons_data = json.load(json_file) # 修改指定项 for button in list(buttons_data.keys()): if button == text: # 更新嵌套字段 buttons_data[button]["text"] = new_text buttons_data[button]["directory"] = new_directory buttons_data[button]["fg_color"] = new_fg_color buttons_data[button]["hover_color"] = new_hover_color # 重命名键,必须赋值回原变量 buttons_data = rename_key(buttons_data, text, new_text) break # 将修改后的内容写回JSON文件 with open(buttons, 'w') as json_file: json.dump(buttons_data, json_file, indent=4)
方法2:兼容Python3.6及以下(使用OrderedDict)
如果需要兼容更早的Python版本,或者更明确地控制顺序,使用collections.OrderedDict:
from collections import OrderedDict import json def rename_ordered_key(od, old_key, new_key): new_od = OrderedDict() for k, v in od.items(): new_od[new_key if k == old_key else k] = v return new_od # 定义要修改的参数 text = "Survival" new_text = "Survival Mods" new_directory = "C:\\Users\\Famille Arcand\\Downloads\\Mods\\Survival Mods\\" new_fg_color = "#1e69a4" new_hover_color = "#144870" # 加载为OrderedDict以保证顺序 with open(buttons, 'r') as json_file: buttons_data = json.load(json_file, object_pairs_hook=OrderedDict) # 修改指定项 for button in list(buttons_data.keys()): if button == text: buttons_data[button]["text"] = new_text buttons_data[button]["directory"] = new_directory buttons_data[button]["fg_color"] = new_fg_color buttons_data[button]["hover_color"] = new_hover_color buttons_data = rename_ordered_key(buttons_data, text, new_text) break # 写回文件 with open(buttons, 'w') as json_file: json.dump(buttons_data, json_file, indent=4)
关键注意事项
- 必须将
rename_key/rename_ordered_key返回的新字典赋值给buttons_data,否则修改不会生效 - Python3.7及以上版本的普通字典默认保留插入顺序,无需额外处理;更早版本需用
OrderedDict - 修改完成后一定要将
buttons_data写回JSON文件,否则修改仅存在于内存中
内容的提问来源于stack exchange,提问作者Cube Rubik
相关产品推荐
相关产品推荐

