Hip*_*Man 5 python json encoder python-3.x
我想将字典转换为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)
Run Code Online (Sandbox Code Playgroud)
我希望这是结果:
{"key-true": 1, "key-a": "a", "key-false": 0}
Run Code Online (Sandbox Code Playgroud)
但是,这就是我得到的:
{"key-true": true, "key-a": "a", "key-false": false}
Run Code Online (Sandbox Code Playgroud)
我知道我可以在传递之前以编程方式修改数据json.dumps,但是有什么办法可以通过JSONEncoder子类获得我想要的结果吗?
只有当编码器遇到一个它不知道如何序列化的对象时,才会调用子类的default()方法JSONEncoder.
不幸的是,官方文档并没有说清楚.它被提到,但是在类构造函数的"关键字参数"部分中,而不是在方法的文档中:
如果指定,则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)
Run Code Online (Sandbox Code Playgroud)
>>> class Foo: pass
...
>>> s = json.dumps({'a': False, 'b': True, 'c': Foo()}, cls=MyEncoder)
got Foo
>>> s
'{"a": false, "c": {"__Foo__": 140636444256856}, "b": true}'
Run Code Online (Sandbox Code Playgroud)
JSONEncoder不是设计为轻松允许覆盖它已知道如何序列化的对象的序列化(这是一件好事:像JSON这样的标准的全部意义在于它们是,嗯,标准)...所以如果你真的想要编码布尔,就好像它们是整数一样,最简单的方法可能是按照问题中的建议预处理数据.