扩展JSONEncoder以调用__json__进行序列化?

时间:2016-07-07 16:29:10

标签: python json serialization

我希望将JSONEncoder扩展为调用对象的__json__,以将其转换为可序列化的内容。

我试过这个:

import json

class Foo(object):

    def __json__(self):
        return dict(a=1, b=2)

class MyJSONEncoder(json.JSONEncoder):
      """
      Use __json__ attr or callable of object for JSON serialization.
      """
      def default(self, o):
          if hasattr(o, '__json__'):
              if callable(o.__json__):
                  o = o.__json__()
              else:
                  o = o.__json__
          return super(MyJSONEncoder, self).default(o)

json.dumps(Foo(), cls=MyJSONEncoder)

得到这个:

Traceback (most recent call last):
  File "./foo.py", line 20, in <module>
    json.dumps(Foo(), cls=MyJSONEncoder)
  File "/usr/lib64/python2.7/json/__init__.py", line 250, in dumps
    sort_keys=sort_keys, **kw).encode(obj)
  File "/usr/lib64/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib64/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
  File "./foo.py", line 18, in default
    return super(MyJSONEncoder, self).default(o)
  File "/usr/lib64/python2.7/json/encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: {'a': 1, 'b': 2} is not JSON serializable

1 个答案:

答案 0 :(得分:1)

我发现了我的错误:

class MyJSONEncoder(DjangoJSONEncoder):                                         
      """                                                                         
      Use __json__ attr or callable of object for JSON serialization.             
      """                                                                         

      def default(self, o):                                                       
          if hasattr(o, '__json__'):                                              
              if callable(o.__json__):                                            
                  return o.__json__() # <----- here                                            
              else:                                                               
                  return o.__json__ # <-------- and here                                              
          return super(MyJSONEncoder, self).default(o)         

初始实现错误地将o.__json__结果链传递给父default(),并假设default()应返回序列化对象..这不是&# 39;它是如何运作的。它需要返回可序列化的对象。

json/encoder.py的来源总结了这一点:

  

要扩展它以识别其他对象,子类并使用另一个方法实现.default()方法,如果可能的话,该方法返回o的可序列化对象,否则它应该调用超类实现(以提升{{ 1}})。