Python实现JSON反序列化类对象的示例
我们的网络协议一般是把数据转换成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 根据文档的解释就是一个自定义解码函数,入参数标准反序列化后的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 。 不看不知道,一看吓一跳,官方文档用了一种巧妙的方式实现了上面的需求。 >>> class JSONObject: ... def __init__(self,d): ... self.__dict__ = d ... >>> >>> data = json.loads(s,object_hook=JSONObject) >>> data.name 'ACME' >>> data.shares 50 >>> data.price 490.1 >>> 我服了,把json解析之后的dict直接赋值给对象的属性dict,然后就可以随心所欲的使用属性了,真心方便,动态语言就是好。 以上是官方的json库实现方案,那另外两个知名的第三方库呢? 二、demjson demjson 也支持 hook 。有两种配置的方式: decode 函数配置和 set_hook 函数配置 1. decode def decode( txt,**kwargs ) decode 函数可以指定很多参数,其中就包括 hook 函数。 hook 函数的指定是使用键值对的方式,键是 hook 函数的名称,值是 hook 函数。 demjson是通过名字来管理hook函数的,所以hookname不是随便指定的,必须是内置的几种hook函数的名称。
demjson.decode(body,encode='utf-8',decode_obbject=Reponse.object_hook) 结果并没有让我很开森,依然是无法处理嵌套结构。 日志中显示如下内容:
很奇怪的是 object_hook 函数被调用了两次,第一次是 data 字段的内容,第二是全部的内容,但是 data 字段没有解析出来。 非常奇怪,百思不得其解!!! 2. set_hook set_hook 函数跟上面的 decode 函数不一样,它是 JSON 类的成员函数,而 decode 函数是个静态函数。 def set_hook(self,hookname,function) 吸取之前的教训,这次我仔细阅读了demjson的文档,还真发现点东西。
这里重点说到嵌套的问题,出现嵌套的时候,每个对应的类型都会调用 hook 函数一次,而且是从最内层,从左往右。好吧,之前出现的问题全部明白了,原来都是这个规则惹的祸,但是为什么这样设计我暂时还是不明白。 set_hook 的使用方式 j = demjson.JSON() j.set_hook( 'decode_array',my_sort_array ) j.decode(body,encode='utf-8') 三、simplejson 前面说了那么多, simplejson 的方式就没什么可说的,跟官方的 json 库 hook 方式一致。 总结 虽然我的需求是满足了,但是还是有一个大大的问号留在我心中,为什么是这样设计,网上没有找到合适的答案,剩下的需要研究源代码分析了。 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。 您可能感兴趣的文章:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |