【问题标题】: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 子类获得我想要的结果?

【问题讨论】:

    标签: python json python-3.x encoder


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

    【讨论】:

      猜你喜欢
      • 2022-11-27
      • 1970-01-01
      • 2012-04-28
      • 1970-01-01
      • 2015-12-16
      • 2014-05-30
      • 2014-07-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多