Python序列化模型資料為JSON

發表於2016-07-01

相信使用Python做Web開發的朋友都會遇到這樣1個問題,那就是在專案開發中使用模型框架,比如SQLAlchemy、Peewee,我們在做RESTful介面時如何將這些模型序列化為JSON資料。
關於這個問題,跟隔壁那位搞Python的哥們有關係。我不得不佩服這位哥們竟然自己寫了1套ORM框架,而且用起來的那麼遛,不得不讓我汗顏。
但是,在給前端提供介面的時候,如何序列化為JSON資料確實困擾了我們那麼一陣子,畢竟佔據我們很大一部分時間來進行序列化操作。
這裡,我們使用peewee來定義1個簡單的例子來說明:

在這裡我們定義了Person和Pet這2個模型,每個Person可能有1個Pet的寵物。
我們插入一些資料,現在假設我們現在有如下的資料:

現在,我們假設我們介面需要返回的介面是每個使用者的名稱、生日及其對應的寵物的資訊。
我們可以通過連表的方式輕鬆的獲取到我們需要的資料:

那麼我們怎麼將這個模型資料轉換為我們需要的JSON資料呢?一般情況下,我們會這樣操作:

最後我們將得到如下的結果:

可以看到,這麼1個簡單的例子,我們已經對序列化操作處理的已經夠嗆的。對於那些更為複雜的模型,我們預計只有哭的份了。
因此,我們希望能找到1個庫可以減輕我們的工作量,於是我們找到了1個marshallow的庫。
下面我們來說說如何使用marshallow來減輕序列化模型的工作量。
主要包括如下2個步驟:

  • 定義模式
  • 序列化模型

下面我們分別來看看。

定義模式

如果你使用過Flask-RESTful,你應該知道該庫提供了1個marshal_with的函式。其中我們就需要定義我們給定欄位返回的資料型別,但是Flask-RESTful沒有提供欄位不同返回的操作。
我們通過如下的方式匯入模式及其對應的欄位:

接下來,我們定義1個繼承自Schema的類,然後定義其對應的欄位:

由於這裡,我們將使用者的name屬性修改為username,因此我們需要在欄位中使用dump_to引數將其修改為我們需要的欄位。另外,使用者的pet欄位對應的是寵物的資訊,因此我們採用巢狀模式來實現這樣需求。

序列化模型

上面我們已經定義好了我們的模式了,下一步是序列化模型的操作了。
我們可以這樣來操作:

接著,我們例項化我們的模式,然後傳入需要序列化的模型:

在這裡,我們呼叫PersonSchema例項的dumps來生成JSON資料,另外它還有1個dump方法用於生成Python物件。由於我們的渲染的資料有多條,因此我們需要在例項化PersonSchema類時傳入關鍵字引數many為True,不然沒有任何資料。
通過這種方式,PersonSchema會檢視它自己的屬性,將資料模型中對應的資料先序列化出來,然後是查詢巢狀模式中的欄位,如果符合對應的名稱則將其序列化出來,最後我們將得到這樣的資料:

可以看到,通過marshallow得到的結果與之前我們編寫的序列化操作的結果是一樣的。
不得不說,marshallow這個庫對於序列化模型其實挺實用的。當然對於複雜的模型,我們需要利用合適的方式將其搜尋出來,不然還是序列化不了的。

參考文章:

https://marshmallow.readthedocs.io/en/latest/quickstart.html

相關文章