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

Posted

技术标签:

【中文标题】为啥我的自定义 JSONEncoder.default() 忽略布尔值?【英文标题】:Why is my custom JSONEncoder.default() ignoring booleans?为什么我的自定义 JSONEncoder.default() 忽略布尔值? 【发布时间】:2018-02-22 13:49:33 【问题描述】:

我想将字典转换为 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】:

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

很遗憾,官方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 这样的标准的全部意义在于它们是,嗯,标准) ...因此,如果您真的想将布尔值编码为整数,那么最简单的方法可能是按照您的问题中的建议预处理数据。

【讨论】:

以上是关于为啥我的自定义 JSONEncoder.default() 忽略布尔值?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的自定义 UITableViewCell 没有显示?

为啥我的自定义 cookiejar 不起作用?

为啥我的自定义 UITableViewCell 在 cellForRowAtIndexPath 中为空?

为啥我的自定义 UITableViewcell 没有显示?

为啥我的自定义 ButtonRenderer 不起作用?

为啥我的自定义 Swift 类没有转移到我的 GameScene [关闭]