Python:用json内置编码任意对象

时间:2017-12-26 10:48:16

标签: python json

我正在编写一个带有Tornado后端的webapp,当然还有前端的javascript和jquery,所以我使用标准库中的内置json模块来序列化前端的对象。我已经开始为我的类编写一个自定义的JSONEncoder,但后来我发现我只能编写一个非常简单的通用对象编码器:

class ObjectEncoder(json.JSONEncoder):
    def default(self, obj):
        return vars(obj)

它似乎工作得很好,所以我想知道为什么这不包含在模块中,如果这种技术有缺点。如果它与check_circular很好地合作,我没有进行实验,但我没有理由相信它没有。

对我怀疑的任何评论?否则,我认为这种技术可能对某些人有用,因为我没有通过搜索找到它(诚然,快速的)。

编辑:这是一个示例,尽可能简单,以显示json模块的行为:

>>> import json
>>> class Foo:
...   def __init__(self):
...     self.bar = 'bar'
... 
>>> foo = Foo()
>>> json.dumps(foo)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/json/__init__.py", line 230, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python3.5/json/encoder.py", line 198, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.5/json/encoder.py", line 256, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python3.5/json/encoder.py", line 179, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <__main__.Foo object at 0x7f14660236d8> is not JSON serializable
>>> class ObjectEncoder(json.JSONEncoder):
...     def default(self, obj):
...         return vars(obj)
... 
>>> json.dumps(foo, cls=ObjectEncoder)
'{"bar": "bar"}'

1 个答案:

答案 0 :(得分:1)

vars(obj)obj.__dict__的语法糖,因此它不适用于没有__dict__的任何对象。这包括以下内容:

  1. 用户定义的对象,其中类层次结构中的每个级别都定义__slots__(没有__dict__个插槽)以减少内存使用量
  2. 不会选择加入tp_dict广告位的内置类型的对象
  3. 更糟糕的是,存在中间情况,其中某些属性在__dict__上设置,而其他属性则不是(例如,某些级别使用__slots__的类层次结构,但是其他级别没有使用__slots__并且依赖于隐式__dict__)。在这样的情况下,你不会得到错误让你知道出了什么问题,你只是序列化对象状态的__dict__部分并默默地忽略其余部分。

    如果界面使用@property s,您会遇到类似的问题;它们像属性一样被使用,但它们不在实例__dict__上,因此您要么完全丢失信息(如果没有隐藏的基础属性),要么序列化& #34;错误&#34; value(内部名称,而不是作为@property公开的API名称)。

    简而言之,通过尝试猜测这样的正确行为,很多事情可能会出现严重错误,这就是为什么Python的Zen(在交互式终端中输入import this来查看它)包括以下内容:

      

    错误绝不应该以无声方式传递。

      

    面对模棱两可,拒绝猜测的诱惑。

    除了这些错误之外,还存在可逆性的一般问题。此表单的常规编码器在定义上无法由常规解码器处理(因为您丢失了所有类型信息)。提供一种丢失重要信息的简便方法是......次优。