Python字典与JSON文件双重循环替换键仅首项生效问题排查
问题根源
核心问题是文件指针耗尽:第一次外层循环遍历self.file_read时,文件指针会移动到文件末尾。后续两次外层循环再尝试读取该文件对象时,已无内容可读,因此只有第一个键值对的替换生效。
修复方案
提供两种可行修复思路,推荐第二种(更高效,减少文件IO操作):
思路1:每次外层循环前重置文件指针
在每次遍历文件前,调用seek(0)将指针重置到文件开头,确保每次外层循环都能重新读取完整文件内容。
修改后的replace_keys方法:
def replace_keys(self): replaced_json = '' for before, after in self.replace_dict.items(): search_phrase = f'"key":"{before}"' additional_search_phrase = f'"key": "{before}"' # 重置文件指针到文件开头 self.file_read.seek(0) # 清空上一次循环的结果,避免重复累加 replaced_json = '' for line in self.file_read: if search_phrase in line or additional_search_phrase in line: replaced_json_line = line.replace(before, after) replaced_json += replaced_json_line else: replaced_json += line print(replaced_json) self.file_read.close()
思路2:先将文件内容读入内存(推荐)
一次性把文件内容读取到内存字符串中,后续直接在内存中完成多次替换,避免反复操作文件,效率更高。
修改后的完整代码:
class Replacer: def __init__(self, form_json_path: str, replace_dict: dict): # 一次性读取文件全部内容到内存 with open(form_json_path, 'r') as f: self.file_content = f.read() self.replace_dict = replace_dict def replace_keys(self): replaced_json = self.file_content for before, after in self.replace_dict.items(): # 替换两种格式的目标字符串 replaced_json = replaced_json.replace(f'"key":"{before}"', f'"key":"{after}"') replaced_json = replaced_json.replace(f'"key": "{before}"', f'"key": "{after}"') print(replaced_json) keys_to_replace = { "antragsumfang_Panel": "antragsumfang_PanelREPLACED", "antragsumfangHinweis_HTMLElement": "antragsumfangHinweis_HTMLElementREPLACED", "antragsumfangHinweisZwei_HTMLElement": "antragsumfangHinweisZwei_HTMLElementREPLACED" } f = Replacer('t.json', keys_to_replace) f.replace_keys()
额外严谨方案
直接操作JSON字符串容易出现误替换(比如键名出现在其他文本中),更稳妥的方式是先解析JSON为Python字典,修改键名后再转回JSON:
import json class Replacer: def __init__(self, form_json_path: str, replace_dict: dict): with open(form_json_path, 'r') as f: self.data = json.load(f) self.replace_dict = replace_dict def replace_keys(self): # 递归遍历字典替换键名 def replace_recursive(obj): if isinstance(obj, dict): new_obj = {} for k, v in obj.items(): new_key = self.replace_dict.get(k, k) new_obj[new_key] = replace_recursive(v) return new_obj elif isinstance(obj, list): return [replace_recursive(item) for item in obj] else: return obj replaced_data = replace_recursive(self.data) print(json.dumps(replaced_data, indent=2)) keys_to_replace = { "antragsumfang_Panel": "antragsumfang_PanelREPLACED", "antragsumfangHinweis_HTMLElement": "antragsumfangHinweis_HTMLElementREPLACED", "antragsumfangHinweisZwei_HTMLElement": "antragsumfangHinweisZwei_HTMLElementREPLACED" } f = Replacer('t.json', keys_to_replace) f.replace_keys()
内容的提问来源于stack exchange,提问作者user16678506
相关产品推荐
相关产品推荐

