Python序列化模型資料為JSON

2021-08-28 20:08:56 字數 3644 閱讀 5290

2016/07/01 · 實踐專案 · orm, web

原文出處: 我勒個去

相信使用python做web開發的朋友都會遇到這樣1個問題,那就是在專案開發中使用模型框架,比如sqlalchemy、peewee,我們在做restful介面時如何將這些模型序列化為json資料。

關於這個問題,跟隔壁那位搞python的哥們有關係。我不得不佩服這位哥們竟然自己寫了1套orm框架,而且用起來的那麼遛,不得不讓我汗顏。

但是,在給前端提供介面的時候,如何序列化為json資料確實困擾了我們那麼一陣子,畢竟佔據我們很大一部分時間來進行序列化操作。

這裡,我們使用peewee來定義1個簡單的例子來說明:

from peewee import sqlitedatabase

from peewee import model, charfield, datefield, booleanfield, foreignkeyfield

db = sqlitedatabase('dev.sqlite3')

class basemodel(model):

class meta:

database = db

class person(basemodel):

name = charfield(max_length= 20)

birthday = datefield()

*** = booleanfield()

class pet(basemodel):

owner = foreignkeyfield(person, related_name= 'pets')

name = charfield(max_length= 10)

animal_type = charfield(max_length= 20)

在這裡我們定義了person和pet這2個模型,每個person可能有1個pet的寵物。

我們插入一些資料,現在假設我們現在有如下的資料:

sqlite> select * from person;

1|bob|1960-01-15|1

2|grandma|1935-03-01|0

3|herb|1950-05-05|1

sqlite> select * from pet;

1|1|kitty|cat

2|3|fido|dog

3|3|mittens|cat

4|2|jack|cat

現在,我們假設我們介面需要返回的介面是每個使用者的名稱、生日及其對應的寵物的資訊。

我們可以通過連表的方式輕鬆的獲取到我們需要的資料:

query=person.select(person,pet).join(pet)

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

data =

for person in query.aggregate_rows():

d={}

d['username'] = person.name

d['birthday'] = person.birthday

d['pet'] =

for pet in person.pets:

o = {}

o['name'] = pet.name

o['animal_type'] = pet.animal_type

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

,'username': u'bob'},,],

'username': u'herb'},

],'username': u'grandma'}]

可以看到,這麼1個簡單的例子,我們已經對序列化操作處理的已經夠嗆的。對於那些更為複雜的模型,我們預計只有哭的份了。

因此,我們希望能找到1個庫可以減輕我們的工作量,於是我們找到了1個marshallow的庫。

下面我們來說說如何使用marshallow來減輕序列化模型的工作量。

主要包括如下2個步驟:

下面我們分別來看看。

如果你使用過flask-restful,你應該知道該庫提供了1個marshal_with的函式。其中我們就需要定義我們給定字段返回的資料型別,但是flask-restful沒有提供字段不同返回的操作。

我們通過如下的方式匯入模式及其對應的字段:

from marshmallow import schema, fields

接下來,我們定義1個繼承自schema的類,然後定義其對應的字段:

class petschema(schema):

name = fields.string()

animal_type = fields.string()

class personschema(schema):

name = fields.string(dump_to = 'username')

birthday = fields.date()

pets = fields.nested(petschema,dump_to='pet',many=true)

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

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

我們可以這樣來操作:

query=person.select(person, pet).join(pet)

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

person, error = personschema(many = true).dumps(query.aggregate_rows())

在這裡,我們呼叫personschema例項的dumps來生成json資料,另外它還有1個dump方法用於生成python物件。由於我們的渲染的資料有多條,因此我們需要在例項化personschema類時傳入關鍵字引數many為true,不然沒有任何資料。

通過這種方式,personschema會檢視它自己的屬性,將資料模型中對應的資料先序列化出來,然後是查詢巢狀模式中的字段,如果符合對應的名稱則將其序列化出來,最後我們將得到這樣的資料:

"username": "bob",

"pet": [

"animal_type": "cat",

"name": "kitty"

"birthday": "1960-01-15"

"username": "herb",

"pet": [

"animal_type": "dog",

"name": "fido"

"animal_type": "cat",

"name": "mittens"

"birthday": "1950-05-05"

"username": "grandma",

"pet": [

"animal_type": "cat",

"name": "jack"

"birthday": "1935-03-01"

可以看到,通過marshallow得到的結果與之前我們編寫的序列化操作的結果是一樣的。

不得不說,marshallow這個庫對於序列化模型其實挺實用的。當然對於複雜的模型,我們需要利用合適的方式將其搜尋出來,不然還是序列化不了的。

序列化(模型序列化 序列化巢狀)

from rest framework import serializers from meituan.models import merchant,class merchantserializer serializers.modelserializer class meta model merch...

python 序列化模組 python 序列化模組

一 介紹 1 分類 序列化 資料型別 字串 反序列化 字串 資料型別 2 作用 檔案傳輸和檔案儲存需要將資料型別轉換成字串 二 序列號模組分類 1 json 優點 程式語言中的英語,同用語言 缺點 資料型別少 數字 字串 列表 字典 元祖 通過列表進行的 2 pickle 優點 python的所有資...

Python 序列化和反序列化

在spark中使用廣播變數時,選擇合適的序列化格式是非常重要的。這裡重點講的是python中的序列化。1.序列化和反序列化 序列化就是把資料變成可儲存或可傳輸的過程的,只有序列化後的資料才可以寫入到磁碟或者通過網路傳輸到spark集群的其他節點上。反序列化則相反,反序列就是把序列化的變數重新轉到記憶...