Python如何實(shí)現(xiàn)JSON反序列化類對象-創(chuàng)新互聯(lián)

這篇文章主要介紹了Python如何實(shí)現(xiàn)JSON反序列化類對象,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

成都網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)建站!專注于網(wǎng)頁設(shè)計(jì)、成都網(wǎng)站建設(shè)公司、微信開發(fā)、小程序制作、集團(tuán)成都定制網(wǎng)站等服務(wù)項(xiàng)目。核心團(tuán)隊(duì)均擁有互聯(lián)網(wǎng)行業(yè)多年經(jīng)驗(yàn),服務(wù)眾多知名企業(yè)客戶;涵蓋的客戶類型包括:社區(qū)文化墻等眾多領(lǐng)域,積累了大量豐富的經(jīng)驗(yàn),同時也獲得了客戶的一致贊賞!

我們的網(wǎng)絡(luò)協(xié)議一般是把數(shù)據(jù)轉(zhuǎn)換成JSON之后再傳輸。之前在Java里面,實(shí)現(xiàn)序列化和反序列化,不管是 jackson ,還是 fastjson 都非常的簡單?,F(xiàn)在有項(xiàng)目需要用Python來開發(fā),很自然的希望這樣的便利也能在Python中體現(xiàn)。

但是在網(wǎng)上看了一些教程,講反序列化的時候,基本都是轉(zhuǎn)換為 dict 或者 array 。這種編程方式我從情感上是無法接受的。難道是這些JSON庫都不支持反序列化為類對象?我馬上打消了這個念頭,Python這樣強(qiáng)大的腳本語言,不可能沒有完善的JSON庫。

于是我就研究了一下原生的 json ,以及第三方的 demjson 和 simplejson 。

一、原生json

我仔細(xì)研究了原生 json 的 loads 方法的定義

復(fù)制代碼 代碼如下:

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 參數(shù)引起了我的注意,我重點(diǎn)說一下 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 根據(jù)文檔的解釋就是一個自定義解碼函數(shù),入?yún)?shù)標(biāo)準(zhǔn)反序列化后的dict,我們可以根據(jù)自己的規(guī)則轉(zhuǎn)換輸出為想要的格式。

我又去搜了一下 object_hook ,大家對于這個東西的處理方式基本就是用一個靜態(tài)方法把dict轉(zhuǎn)換成對象。

我們的數(shù)據(jù)結(jié)構(gòu)是這樣的

{"status":1,"info":"發(fā)布成功","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)

一開始呢,確實(shí)沒有問題,雖然用起來沒有java的json庫辣么方便,但總歸實(shí)現(xiàn)了需求。

好景不長,我測試的第一個接口返回的數(shù)據(jù)中, data 是字段一個字符串,反序列化正常??墒呛髞懋?dāng)接口返回的結(jié)構(gòu)中 data 字段是一個dict結(jié)構(gòu)的時候, object_hook 的入?yún)⒕尤蛔兂闪?data 字段轉(zhuǎn)換之后的dict( {"id":"52","feed_id":"70"} ),而不是完整的數(shù)據(jù)。

這些懵逼了,上網(wǎng)搜索了一圈沒有結(jié)論。于是上網(wǎng)搜了一圈,也沒有結(jié)論。 好吧,我最后又回到官方文檔, read the fucking official document 。

不看不知道,一看嚇一跳,官方文檔用了一種巧妙的方式實(shí)現(xiàn)了上面的需求。

>>> 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,然后就可以隨心所欲的使用屬性了,真心方便,動態(tài)語言就是好。

以上是官方的json庫實(shí)現(xiàn)方案,那另外兩個知名的第三方庫呢?

二、demjson

demjson 也支持 hook 。有兩種配置的方式: decode 函數(shù)配置和 set_hook 函數(shù)配置

1. decode

def decode( txt, encoding=None, **kwargs )

decode 函數(shù)可以指定很多參數(shù),其中就包括 hook 函數(shù)。 hook 函數(shù)的指定是使用鍵值對的方式,鍵是 hook 函數(shù)的名稱,值是 hook 函數(shù)。

demjson是通過名字來管理hook函數(shù)的,所以hookname不是隨便指定的,必須是內(nèi)置的幾種hook函數(shù)的名稱。

  1. decode_number

  2. decode_float

  3. decode_object

  4. decode_array

  5. decode_string

  6. encode_value

  7. encode_dict

  8. encode_dict_key

  9. encode_sequence

  10. encode_bytes

  11. encode_default

demjson.decode(body, encode='utf-8',decode_obbject=Reponse.object_hook)

結(jié)果并沒有讓我很開森,依然是無法處理嵌套結(jié)構(gòu)。 日志中顯示如下內(nèi)容:

2018-01-30 16:01:17,137 poster.py post_all 73 INFO    : {"status":1,"info":"\u53d1\u5e03\u6210\u529f","data":{"id":"54","feed_id":"72"}}
2018-01-30 16:01:17,138 response.py object_hook 13 INFO    : {'id': '54', 'feed_id': '72'}
2018-01-30 16:01:17,138 response.py object_hook 13 INFO    : {'status': 1, 'info': '發(fā)布成功', 'data': demjson.undefined}

很奇怪的是 object_hook 函數(shù)被調(diào)用了兩次,第一次是 data 字段的內(nèi)容,第二是全部的內(nèi)容,但是 data 字段沒有解析出來。 非常奇怪,百思不得其解!?。?/p>

2. set_hook

set_hook 函數(shù)跟上面的 decode 函數(shù)不一樣,它是 JSON 類的成員函數(shù),而 decode 函數(shù)是個靜態(tài)函數(shù)。

def set_hook(self, hookname, function)

吸取之前的教訓(xùn),這次我仔細(xì)閱讀了demjson的文檔,還真發(fā)現(xiàn)點(diǎn)東西。

Netsted values. When decoding JSON that has nested objects or arrays, the decoding hooks will be called once for every corresponding value, even if nested. Generally the decoding hooks will be called from the inner-most value outward, and then left to right.

這里重點(diǎn)說到嵌套的問題,出現(xiàn)嵌套的時候,每個對應(yīng)的類型都會調(diào)用 hook 函數(shù)一次,而且是從最內(nèi)層,從左往右。好吧,之前出現(xiàn)的問題全部明白了,原來都是這個規(guī)則惹的禍,但是為什么這樣設(shè)計(jì)我暫時還是不明白。

set_hook 的使用方式

j = demjson.JSON()
  j.set_hook( 'decode_array', my_sort_array )
  j.decode(body, encode='utf-8')

三、simplejson

前面說了那么多, simplejson 的方式就沒什么可說的,跟官方的 json 庫 hook 方式一致。

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Python如何實(shí)現(xiàn)JSON反序列化類對象”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司,關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、網(wǎng)站設(shè)計(jì)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

名稱欄目:Python如何實(shí)現(xiàn)JSON反序列化類對象-創(chuàng)新互聯(lián)
網(wǎng)站地址:http://muchs.cn/article10/egggo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、品牌網(wǎng)站設(shè)計(jì)建站公司、網(wǎng)站維護(hù)、網(wǎng)站收錄Google

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站