我们的网络协议一般是把数据转换成JSON之后再传输。之前在Java里面,实现序列化和反序列化,不管是 jackson ,还是 fastjson 都非常的简单。现在有项目需要用Python来开发,很自然的希望这样的便利也能在Python中体现。
但是在网上看了一些教程,讲反序列化的时候,基本都是转换为 dict 或者 array 。这种编程方式我从情感上是无法接受的。难道是这些JSON库都不支持反序列化为类对象?我马上打消了这个念头,Python这样强大的脚本语言,不可能没有完善的JSON库。
于是我就研究了一下原生的 json ,以及第三方的 demjson 和 simplejson 。
一、原生json
我仔细研究了原生 json 的 loads 方法的定义
复制代码 代码如下:
def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
这里面的 object_hook 和 object_pairs_hook 参数引起了我的注意,我重点说一下 object_hook 。
官方文档的说明如下:object_hook is an optional function that will be called with the result of any object literal decoded (a dict). The return value of object_hook will be used instead of the dict. This feature can be used to implement custom decoders (e.g. JSON-RPC class hinting).
这个 object_hook 根据文档的解释就是一个自定义解码函数,入参数标准反序列化后的dict,我们可以根据自己的规则转换输出为想要的格式。
我又去搜了一下 object_hook ,大家对于这个东西的处理方式基本就是用一个静态方法把dict转换成对象。
我们的数据结构是这样的
{"status":1,"info":"发布成功","data":{"id":"52","feed_id":"70"}}
于是我就写了这样的代码:
class Response:
def __init__(self, status, info, data) -> None:
super().__init__()
self.status = status
self.info = info
self.data = data
@staticmethod
def object_hook(d):
return Response(d['status'], d['info'], d['data'])
...
resp = json.loads(body, object_hook=Response.object_hook)
一开始呢,确实没有问题,虽然用起来没有java的json库辣么方便,但总归实现了需求。
好景不长,我测试的第一个接口返回的数据中, data 是字段一个字符串,反序列化正常。可是后来当接口返回的结构中 data 字段是一个dict结构的时候, object_hook 的入参居然变成了 data 字段转换之后的dict( {“id”:”52″,”feed_id”:”70″} ),而不是完整的数据。
这些懵逼了,上网搜索了一圈没有结论。于是上网搜了一圈,也没有结论。 好吧,我最后又回到官方文档, read the fucking official document 。