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

Why is my custom JSONEncoder.default() ignoring booleans?

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

JSONEncoder subclasses 的 default() 方法仅在编码器遇到它不知道如何序列化的对象时被调用。

不幸的是,官方documentation并没有说得很清楚。它被提及,但在 class 构造函数的 "keyword arguments" 部分中,而不是在该方法的文档中:

If specified, default should be a function that gets called for objects that can’t otherwise be serialized. It should return a JSON encodable version of the object or raise a TypeError. If not specified, TypeError is raised.

这种行为很容易验证:

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 这样的标准的全部意义在于它们'嗯,好吧,standard) …所以如果你真的想把布尔值编码成整数,最简单的方法可能是按照你的问题中的建议预处理数据。