2017-06-12 39 views
0

我正在使用python序列化一個python對象以將其存儲在我的緩存中。對於這個序列化,我使用json.dumps()並在將其從緩存中取出後進行反序列化,我使用的是json.loads()。我認爲這次往返不會有任何問題。但正如你可以在下面看到它失敗。爲什麼python的json.loads/dumps往返有損?

>>> import json 
>>> from collections import namedtuple 
>>> x = {"hello": 1, "goodbye": 2} 
>>> y = namedtuple('Struct', x.keys())(*x.values()) 
>>> y 
Struct(goodbye=2, hello=1) 

>>> json.loads(json.dumps(y)) 
[2, 1]   # <= I expected this to be the same value as y above!! 

爲什麼這個json.dumps/loads往返有損?我可以使用什麼函數將該對象序列化爲該非序列化將保留其原始值?我試圖使用pickle,但它無法序列化對象。

+0

JSO ñ不知道有關命名的信息。 –

+2

JSON並不是要處理任意的用戶定義的對象類型。 JSON支持對應於Python'dict'的「json對象」和對應於Python'list'的「JSON數組」。很顯然,python的'json'模塊假定如果你傳遞一個'tuple',它就會被序列化爲一個JSON數組。但是這總是會被反序列化爲一個Python列表。你可以使用'pickle'來序列化由'namedtuple'返回的類型,但是你必須保持類型。你創建這個類型,實例化這個類型,然後扔掉這個類型:'''''''''''''''''''''' –

+1

@ juanpa.arrivillaga爲什麼不從這個長評論中作出回答? –

回答

3

json嘗試根據其類型序列化對象。它不能序列化任何對象,但只有「基本」的對象,如tuple(轉換爲方括號list),dictlist ...(當然還有整數,字符串,浮點數)。

當使用isinstance測試你的對象,它成功在tuple因爲namedtuple旨在從tuple繼承:

y = namedtuple('Struct', x.keys())(*x.values()) 
print(isinstance(y,tuple)) 

結果是True

所以在encoder.py文件中json模塊,你的數據在iterencode方法匹配isinstance測試(下面的代碼提取物,周圍線311對我的Python 3.4版本):

if isinstance(value, (list, tuple)): 
     chunks = _iterencode_list(value, _current_indent_level) 

因此,任何類型的繼承listtuple被序列像list

在這裏提出一個針對解決方法:Serializing a Python namedtuple to json

相關問題