python Json的一點收穫,自定義序列化方法

 

PyMOTW: json

  • 模塊: json
  • 目的: JavaScript對象格式序列器
  • python版本: 2.6

json模塊提供了一個類似於pickle中用於轉換內存中python對象爲一個序列表示形式(“JavaScript Object Notation”)的API接口. 但和pickle不同的是, JSON在其他很多語言中都有對應實現(特別是在JavaScript中), 使其更適用於內部應用間的通信. 在一個AJAX應用中, JSON可能對於web服務器和客戶端間的通信, 使用最爲廣泛, 但它也不僅限於這類應用.

 

 

 

簡單數據類型的編碼和解碼

編碼器默認支持Python的本地類型(如int, float, list, tuple, dict).

 

 

 

編碼器處理之後的值和Python的repr()的輸出值很類似.

 

編碼之後的解碼所獲的的值可能和原先的對象不是完全一致.

 

比如說, 元組會被轉換爲JSON的列表.

 

 

人性化使用 vs 緊湊型輸出

JSON優於pickle的另外一點是其結果具有可讀性. dumps()函數接收多個參數用於更好的輸出結構. 比如說. sort_keys參數告訴編碼器按照順序輸出字典的鍵值, 而不是隨機無序的.

 

排序之後更容易讓人看出結果, 也使進行JSON的比較輸出成爲可能.

 

 

對於高度嵌套的數據結構, 你會想在輸出結果中增加縮進以更好的顯示其格式.

 

當indent參數是一非負整數時, 輸出的結構和pprint更爲接近, 在每個縮進層次上都有前導空格.

 

像這種類型輸出的數據在傳輸過程中需佔用更多的字節, 不過, 在實際生產環境中沒有必要使用縮進格式. 實際上, 你可以設置數據的分隔符來讓結果更爲緊湊.

 

dumps()函數的separators參數是一個元組, 包含分隔列表各項和字典鍵值各項的字符串. 默認是(‘, ‘, ‘: ‘). 可以去掉後者中的空格, 我們可以得到較緊湊的輸出.

 

 

編碼字典

JSON格式中, 字典的鍵被限制爲字符串類型. 如果字典中的鍵是其他類型, 那麼在編碼這個對象時會產生一個TypeError異常. 一種解決這個限制的方法是, 在編碼時, 使用skipkeys參數跳過所有非字符串類型的鍵.

 

非字符串類型的鍵被忽略, 而不拋出一個異常.

 

 

自定義類型的處理

上面所有的例子都是用了Python的內置類型作爲例子, 因爲他們都被json本身支持. 當然, 自定義類型也常常需要正確編碼. 這裏有兩種情況:

第一, 對於一個類的編碼:

 

編碼一個MyObj對象的最簡單方式是定義個轉換函數, 用於將位置類型轉換出呢個已知類型. 你沒有必要自己進行編碼, 而僅需要將一個對象轉換成另一個對象.

 

在convert_to_builtin_type()函數中, 不被json識別的類對象被轉換成一個包含足夠能重建這個對象的字典信息.

 

 

爲了能解碼結果數據並創建一個MyObj實例, 我們需要配合解碼器以便可以從模塊中導入類並創建實例. 我們在loads()函數中使用object_hook參數.

在輸入數據流中, 對於解碼獲得的每個字典都會調用object_hook, 將這個字典轉換成其他類型的對象. hook函數返回的是調用程序所需要的對象, 而不是字典.

 

由於json將字符串值轉換成unicode對象, 所以我們需要將作爲類構造器的參數重新編碼爲ASCII字符串.

 

 

對於內置類型也都有類似的hooks, 如整型(parse_int), 浮點型(parse_float), 常量(parse_constant).

編碼和解碼類

除了上述的這些函數外, json模塊還提供了編碼和解碼類. 直接使用這些類, 你可以訪問到額外的API接口或者定製創建它的子類.

JSONEncoder提供了一個產生編碼數據”塊”的的迭代接口, 這在寫入一個文件或網絡sockets時(不需要在內存中完整表示整個數據)是非常方便的,

 

正如你看到的, 數據是以邏輯單位形式輸出的, 而不是按照數據長度輸出.

 

 

encode()方法基本上等價於’‘.join(encoder.iterencode()), 只是多了些附加錯誤檢查.

爲了能夠編碼任何類型的對象, 我們可以編寫一類似於上述的convert_to_builtin_type()函數去重載default()方法.

 

這裏輸出的結果是和先前的實現一致的.

 

解碼後將字典轉換成一個對象, 在先前實現的基礎上稍作修改即可.

 

輸出結果也是和先前例子中輸出的一樣.

 

 

流和文件的處理

到目前爲止的所有例子, 我們都假設待編碼的數據都是一次性完整加載到內存中的. 但對於大型數據結構來說, 將編碼數據直接寫入一個類文件對象, 可能會更好. load()和dump()函數可以接收一個用於讀或寫的類文件對象的引用.

 

對於socket來說, 也和正常文件句柄類似.

 

雖然一次性讀取部分數據不是很好, 但是load()函數仍然提供了從流數據輸入中封裝生成對象的功能.

 

 

 

混合數據流

JSONDecoder包含了raw_decode()方法, 用於解碼在很多數據組成的數據結構, 例如包含多餘文本的JSON數據. 返回的值是從輸入數據中解碼獲得的對象, 數據中的index表示解碼對象結束時所在的位置.

 

不幸的是, 這僅僅在對象出現在輸入流的開始處纔有效.

 

 

原文地址:http://vbarter.cn/pymotw/documents/json.html

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章