为什么我的自定义JSONEncoder.default()忽略了布尔值?

时间:2017-09-13 18:27:42

标签: python json python-3.x encoder

我想将字典转换为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子类获得我想要的结果吗?

1 个答案:

答案 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这样的标准的全部意义在于它们是'好吧,标准)...所以如果你真的想把布尔值编码为整数,那么最简单的方法就是根据问题的建议对数据进行预处理。