Django 再談一談json序列化
我們知道JSON字符串是目前流行的數(shù)據(jù)交換格式,在pyhton中我們通過json模塊,將常用的數(shù)據(jù)類型轉(zhuǎn)化為json字符串。但是,json支持轉(zhuǎn)化的數(shù)據(jù)類型是有限的。
比如,我們通過ORM從數(shù)據(jù)庫查詢出的結(jié)果,試圖通過json序列化:
from .models import UserInfo def index(request): user_list = UserInfo.objects.all() import json return HttpResponse(json.dumps(user_list)) # TypeError: Object of type 'QuerySet' is not JSON serializable
報錯,QuerySet不是JSON能序列化的對象。那么有什么辦法可以解決呢?
注意,如果是通過values查詢,如UserInfo.objects.values("name")
,查詢出來的結(jié)果雖然也是QuerySet對象,但是其結(jié)構(gòu)是這樣的:<QuerySet [{'name': 'egon'}, {'name': 'sb'}]>
, 類似于列表套字典的結(jié)構(gòu)。對于這種情況,我們可以通過list()方法將QuerySet 對象轉(zhuǎn)化為列表,這樣就可以直接用json.dumps()
進(jìn)行序列化了。
方法一:serializers
def index(request): user_list = UserInfo.objects.all() from django.core import serializers user_list_json = serializers.serialize("json", user_list) return HttpResponse(user_list_json)
將返回的結(jié)果放到bejson校驗(yàn)結(jié)果如下:
[ { "model": "app01.userinfo", "pk": 1, "fields": { "name": "egon", "pwd": "123" } }, { "model": "app01.userinfo", "pk": 2, "fields": { "name": "sb", "pwd": "123" } } ]
注:pk代表主鍵(可以是默認(rèn)的id主鍵字段,也可以是用戶自定義的主鍵字段)
觀察序列化結(jié)果,發(fā)現(xiàn)這種方式將服務(wù)端數(shù)據(jù)庫的表名都暴露了;另外serializers不支持連表序列化,只能拿到另一張表的id。下面我們我們用一種新的方式。
方法二:自定義JSON處理器
查看json.dumps源碼,發(fā)現(xiàn)序列化時,用到了一個參數(shù)cls = JSONEncoder,我們可以繼承它,自定義一個類,重寫它的default方法,來處理我們需要的數(shù)據(jù)類型。比如自定義對時間對象進(jìn)行轉(zhuǎn)化:
import json from datetime import date from datetime import datetime class JsonCustomEncoder(json.JSONEncoder): def default(self, field): if isinstance(field, datetime): return field.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(field, date): return field.strftime('%Y-%m-%d') else: return json.JSONEncoder.default(self, field)
下面我們試著序列化一個datetime對象:
def index(request): now = datetime.now() import json return HttpResponse(json.dumps(now, cls=JsonCustomEncoder))
再次訪問http://127.0.0.1:8000/index.html:
補(bǔ)充知識:Django ORM對象Json序列化問題
碰到了一個問題:在使用json.dumps()序列化Django ORM的Queryset對象,傳遞給前端的時候,程序報錯:
Object of type 'QuerySet' is not JSON serializable
在python 中,常用的json 的序列化是從simplejson 基礎(chǔ)上改變而來。這個json 包主要提供了dump,load 來實(shí)現(xiàn)dict 與 字符串之間的序列化與反序列化,這很方便的可以完成,但現(xiàn)在的問題是,這個json包不能序列化 django 的models 里面的對象的實(shí)例。
經(jīng)過一番度娘搜索,發(fā)現(xiàn)有如下解決方案:
使用django.core自帶的serializers模塊:
#django ORM的 Queryset對象默認(rèn)無法被直接json.dumps()序列化,django.core提供的serializers模塊提供將其序列化成str類型 #的功能,serializers處理后,再次json.dumps傳給前端,前端需要經(jīng)過兩次json.Parse()處理,才能得到原對象類型,但是格式發(fā) #生了變化,需要按新的方式取索引.例如:obj['pk']取主鍵,obj['fields']["caption"]取obj的caption字段 由QuerySet:[<Business: Business object>] 變?yōu)榱耍? [{"model": "cmdb.business", "pk": 1, "fields": {"caption": "develop"}}]
這樣前端就可以正常獲取數(shù)據(jù)了,只不過此字段需要兩次json.Parse()處理。
至于使用models.Host.objects.get(id=xx)的方式獲取到單個對象,而非Queryset對象,serializers默認(rèn)也無法處理的問題,可以自定義json方法來實(shí)現(xiàn)dumps序列化
json默認(rèn)只支持python原生的list、tuple、dict數(shù)據(jù)類型對象的序列化,若需要擴(kuò)展其他類型對象的序列化功能,可以這樣修改:
import json as default_json from json.encoder import JSONEncoder class BaseResponse(object): def __init__(self): self.status = True self.message = None self.data = None self.error = None o=BaseResponse() class JsonCustomEncoder(JSONEncoder): def default(self, o): if isinstance(o, BaseResponse): return o.__dict__ return JSONEncoder.default(self, o) o1=json.dumps(o,cls=JsonCustomEncoder) >>> print(o1) {"message": null, "error": null, "data": null, "status": true} >>> print(type(o1)) <class 'str'> #在序列化時指定cls參數(shù),cls=自定義的序列化類,在自定義序列化類的default方法中判斷,如果是指定的類的實(shí)例的話,則將該類轉(zhuǎn)換成dict格式返回,若指定類的實(shí)例,則使用json模塊默認(rèn)的序列化方法。最終得到的return值為str類型。
以上這篇Django 再談一談json序列化就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python制作數(shù)據(jù)預(yù)測集成工具(值得收藏)
這篇文章主要介紹了Python如何制作數(shù)據(jù)預(yù)測集成工具,幫助大家進(jìn)行大數(shù)據(jù)預(yù)測,感興趣的朋友可以了解下2020-08-08python實(shí)現(xiàn)接口并發(fā)測試腳本
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)接口并發(fā)測試腳本,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-06-06pandas如何統(tǒng)計(jì)某一列或某一行的缺失值數(shù)目
這篇文章主要介紹了pandas如何統(tǒng)計(jì)某一列或某一行的缺失值數(shù)目,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-05-05在Python中如何傳遞任意數(shù)量的實(shí)參的示例代碼
這篇文章主要介紹了在Python中如何傳遞任意數(shù)量的實(shí)參的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03PyTorch中的參數(shù)類torch.nn.Parameter()詳解
這篇文章主要給大家介紹了關(guān)于PyTorch中torch.nn.Parameter()的相關(guān)資料,要內(nèi)容包括基礎(chǔ)應(yīng)用、實(shí)用技巧、原理機(jī)制等方面,文章通過實(shí)例介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02