JSON文件出现重复键问题:缓存装饰器执行异常排查
JSON缓存文件出现重复键的原因及解决方法
问题背景
现有一个计算数字10次方的函数rui,通过装饰器实现结果缓存:重复输入相同数字时直接返回JSON文件中的缓存值,首次输入则将数字与结果存入JSON文件。代码如下:
import json def decor(func): def wraps(num): with open('inf.json') as json_file: dictionary = json.load(json_file) if num not in dictionary: with open('inf.json', 'w') as json_file: dictionary.update({num : func(num)}) json.dump(dictionary, json_file) return dictionary[num] return wraps @decor def rui(num): return num**10
现象
初始JSON文件为空,执行以下调用:
rui(10) rui(11) rui(10)
预期JSON内容:
{"10" : 10000000000, "11" : 25937424601}
实际JSON内容:
{"10": 10000000000, "11": 25937424601, "10": 10000000000}
再次执行:
rui(11) rui(10) rui(10) rui(15) rui(15)
实际JSON内容出现重复的"15"键:
{"10": 10000000000, "11": 25937424601, "15": 576650390625, "15": 576650390625}
原因分析
核心问题是类型不匹配:
- 函数
rui接收的num是整数类型(比如10) - JSON文件的键只能是字符串类型,
json.load读取后,字典的键会自动转为字符串(比如"10") - 判断
num not in dictionary时,整数10和字符串"10"被视为完全不同的键,导致每次传入整数num都会被判定为“未缓存”,进而重复向字典中添加键值对 - 执行
json.dump时,所有非字符串类型的键会被强制转换为字符串,最终就出现了重复的字符串键
解决方法
统一键的类型:将传入的num转换为字符串后再进行缓存判断与存储,确保JSON中的键和判断用的键类型一致。修改后的代码如下:
import json def decor(func): def wraps(num): # 将num转为字符串,统一键类型 num_key = str(num) with open('inf.json') as json_file: dictionary = json.load(json_file) if num_key not in dictionary: result = func(num) dictionary[num_key] = result with open('inf.json', 'w') as json_file: json.dump(dictionary, json_file) return dictionary[num_key] return wraps @decor def rui(num): return num**10
验证效果
执行相同调用后,JSON文件会正确存储唯一的键值对,不会再出现重复键。
内容的提问来源于stack exchange,提问作者xSAMx
相关产品推荐
相关产品推荐

