1. 程式人生 > >python序列化和JSON

python序列化和JSON

為什麼把這兩個放到一起,理由很簡單,不過暫時不解釋。

一,先看python提供的序列化模組pickle

import pickle

l = ['柯基', '小李', '大華']

lw = pickle.dumps(l) # 把物件轉乘位元組流 也就是序列化
print(lw)
with open('l.txt', 'wb') as f:  #位元組流寫入檔案
    f.write(lw)

with open('l.txt', 'rb') as f:  #從檔案中讀取位元組流
    lr = f.read()
newl = pickle.loads(lr)     #把位元組流轉換成物件
print(newl)

Output:
b'\x80\x03]q\x00(X\x06\x00\x00\x00\xe6\x9f\xaf\xe5\x9f\xbaq\x01X\x06\x00\x00\x00\xe5\xb0\x8f\xe6\x9d\x8eq\x02X\x06\x00\x00\x00\xe5\xa4\xa7\xe5\x8d\x8eq\x03e.'
['柯基', '小李', '大華']

大段程式碼都是檔案操作,因為要儲存起來嘛,所以真正的序列化和反序列化非常簡單,dumps()和loads()就結束了。

緊接著看一個簡化版就好理解了:

import pickle

l = ['柯基', '小李', '大華']

with open('l.txt', 'wb') as f:
    pickle.dump(l, f)

with open('l.txt', 'rb') as f:  #從檔案中讀取位元組流
    newl = pickle.load(f)
print(newl)

Output:
['柯基', '小李', '大華']

就是提供了兩個新的函式dump()和load()把寫入檔案從檔案讀這個過程也給封裝了。

二,JSON--JSON是UTF-8編碼,因為要在網路上傳輸嘛 節約

現在來回答這個問題,很明顯,用pickle序列化的東西,只能用pickle去反序列化,實際上你開啟儲存pickle序列化的檔案,裡面全是一些亂碼,所以上面的資料傳輸就現在了python系統內部。JSON就是用來解決這個問題的,JSON是JavaScript的物件表示法,但是因為各種優點,就成了網路上傳輸資料的一種標準格式。所以把物件序列化乘JSON格式,就可以和其他語言進行通訊。

python也內建了json模組:

import json

l = ['柯基', '小李', '大華']
print(json.dumps(l))    #把python物件轉成json物件
newl = json.loads('["\u67ef\u57fa", "\u5c0f\u674e", "\u5927\u534e"]')    #把json物件轉成python物件
print(newl)

Output:
["\u67ef\u57fa", "\u5c0f\u674e", "\u5927\u534e"]
['柯基', '小李', '大華']

當然也有dump()和load() 這裡不演示了。可以看到python的list就直接被轉換成了json的陣列[],其餘的還有python的dict會被轉換成json的物件{}。

題外話:學到這裡,我才明白為什麼說python簡單,容易入門, 其一是因為內建了大量有用的模組,其二是它這個介面設計的,都一樣- -,用起來你就很舒服。

三,接下來看看怎麼用josn序列化類

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

def Person2Dict(p):
    return{
        'name':p.name,
        'age':p.age
    }

p = Person('張三',33)
print(json.dumps(p, default=Person2Dict, ensure_ascii=False)) #ensure_ascii=False中文不按ascii編碼

Output:
{"name": "張三", "age": 33}

這裡dumps()方法多了一個default屬性,就是告訴json模組怎麼把我的類轉換成json物件,可以看到 Person2Dict實際上是把我們自定義的型別轉換成了可以序列化的基本型別。然後dumps實際是去序列化這個基本型別去了。

再看反序列化:

def Dict2Person(d):
    return Person(d['name'], d['age'])
jsonStr = '{"name": "張三", "age": 33}'

#newP = json.loads(jsonStr)
#newP = Dict2Person(newP)
newP = json.loads(jsonStr, object_hook=Dict2Person)

print(newP.name, newP.age)

Output:
張三 33

可以想想loads()新增object_hook引數之後,就相當於上面註釋掉的兩句程式碼,先轉成dict,然後再用我們寫好的方法去例項化物件。

總結一下就是,python不能序列化自定義的類,需要我們去自己寫一個函式把自定義的類轉換成可以序列化的物件,比如list,dict這類。