2017-09-13 145 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

相關問題