我想将字典转换为JSON字符串,其中布尔True
值转换为数字1
,布尔False
值转换为数字0
。我正在使用JSONEncoder
子类,但似乎忽略了布尔...
import json
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, bool):
return 1 if obj else 0
return super().default(obj)
data = { 'key-a' : 'a', 'key-true' : True, 'key-false' : False }
jsondata = json.dumps(data, cls=MyEncoder)
print(jsondata)
我希望这是结果:
{"key-true": 1, "key-a": "a", "key-false": 0}
但是,这就是我得到的:
{"key-true": true, "key-a": "a", "key-false": false}
我知道我可以在将数据传递给json.dumps
之前以编程方式修改数据,但是有什么方法可以通过JSONEncoder
子类获得我想要的结果吗?
答案 0 :(得分:8)
只有当编码器遇到一个它不知道如何序列化的对象时,才会调用default()
子类的JSONEncoder
方法。
不幸的是,官方documentation并未明确表达这一点。它已经提到了,但在"关键字参数"类构造函数的部分,而不是方法的文档:
如果指定, default 应该是为无法以其他方式序列化的对象调用的函数。它应返回对象的JSON可编码版本或引发
TypeError
。如果未指定,则会引发TypeError
。
可以轻松验证此行为:
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, bool):
print('got bool')
return 1 if obj else 0
if isinstance(obj, Foo):
print('got Foo')
return {'__Foo__': id(obj)}
print('got unknown')
return super().default(obj)
>>> class Foo: pass
...
>>> s = json.dumps({'a': False, 'b': True, 'c': Foo()}, cls=MyEncoder)
got Foo
>>> s
'{"a": false, "c": {"__Foo__": 140636444256856}, "b": true}'
JSONEncoder
并非旨在轻松覆盖已经知道如何序列化的对象的序列化(这是一件好事:像JSON这样的标准的全部意义在于它们是'好吧,标准)...所以如果你真的想把布尔值编码为整数,那么最简单的方法就是根据问题的建议对数据进行预处理。