2017-09-13 147 views
2

我想将字典转换为JSON字符串,其值为布尔值True,将值翻译为1,将布尔值False的值翻译为0。我使用的是JSONEncoder子类,但它似乎忽略布尔...为什么我的自定义JSONEncoder.default()忽略布尔值?

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子类获得我想要的结果吗?

回答

4

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

不幸的是,官方documentation并没有说得这么清楚。它提到,但对于类构造函数的“关键字参数”一节中,而不是在该方法的文档:

如果指定,默认应该是一个被调用的对象功能,可以不否则被序列化。它应该返回一个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这样的标准的全部意义在于它们是,标准)...所以如果你真的想编码布尔值,就好像它们一样是整数,最简单的方法是按照您的问题所建议的预处理数据。

+1

答复接受,谢谢。 – HippoMan

相关问题