在Django中使用json.Encoder:为何handle_json的print未输出?
问题:为什么json.dumps的default函数里的print没输出?
嘿,我来帮你搞明白这个情况!你遇到的问题核心在于json.dumps的default参数只负责处理无法序列化的字典value,完全不会管字典的key。
看你的代码,字典里的key都是datetime.date对象,而JSON规范要求所有key必须是字符串类型。但json.dumps在处理这类非字符串key的时候,不会调用default函数,而是直接尝试把key转成字符串(比如调用str(obj)),所以你的handle_json函数从始至终都没被执行过,自然看不到print的输出。
验证这个逻辑
你可以做个小测试:把date对象放到value的位置,比如:
def test_json(): data= {"test_date": datetime.date(2018, 12, 1)} print(json.dumps(data, default=handle_json))
这时候handle_json就会被触发,控制台也会打印出那个date对象。
解决办法
如果你想处理字典里的date类型key,有两种常用方式:
1. 提前把key转换成字符串
直接在构造字典的时候,把date对象转成字符串,这样json.dumps就能正常处理,也可以按需在default里处理其他value:
import json import datetime def handle_json(obj): print(obj) if isinstance(obj, datetime.date): return str(obj) return obj def test_json(): # 先将date类型的key转为字符串 data = { str(datetime.date(2018, 12, 1)): 160000.0, str(datetime.date(2019, 2, 1)): 240000.0, str(datetime.date(2020, 9, 1)): 1360000.0, str(datetime.date(2019, 3, 1)): 280000.0 } print(json.dumps(data, default=handle_json))
2. 自定义JSONEncoder处理key
如果不想提前转换,可以自定义一个Encoder,重写encode方法来处理字典的key,同时用default处理value:
import json import datetime class DateKeyJSONEncoder(json.JSONEncoder): def encode(self, obj): # 先处理字典的key:把非字符串的key转成可序列化的格式 if isinstance(obj, dict): obj = {self.default(k): v for k, v in obj.items()} return super().encode(obj) def default(self, obj): # 处理date类型的对象(不管是key还是value) if isinstance(obj, datetime.date): print(obj) return str(obj) # 其他类型交给父类处理 return super().default(obj) def test_json(): data= {datetime.date(2018, 12, 1): 160000.0, datetime.date(2019, 2, 1): 240000.0, datetime.date(2020, 9, 1): 1360000.0, datetime.date(2019, 3, 1): 280000.0} print(json.dumps(data, cls=DateKeyJSONEncoder))
这样运行后,你就能看到Encoder里的print输出每个date对象了。
内容的提问来源于stack exchange,提问作者108
相关产品推荐
相关产品推荐

