Django后端接收嵌套Json數(shù)據(jù)及解析詳解
0、干貨先寫在前
1、前端傳值的數(shù)據(jù)必須使用JSON.stringify()傳化
2、后端,通過(guò)request.body接收數(shù)據(jù),直接使用json.loads解析,解析前,先decode一下:receive_data = json.loads(request.body.decode())。如果使用simplejson.loads(request.body),就不用decode()
下面是這個(gè)問(wèn)題產(chǎn)生及解決的過(guò)程,還有一些可能的應(yīng)用場(chǎng)景。
1、傳統(tǒng)方式解析表單數(shù)據(jù)
之前用Django后臺(tái)接收數(shù)據(jù)的時(shí)候,一直采用的是表單的形式,通過(guò)Ajax傳值的時(shí)候也是一樣,直接通過(guò)鍵值對(duì)兒將值傳遞給后臺(tái),前端代碼類似這樣:
$.post("/login/", { "user":"threedog", "password":"123456" }, function (res) { console.log(res) });
在后臺(tái)采用`request.POST`進(jìn)行數(shù)據(jù)接收:
class Login(View): def get(self,request): return render(request,'login.html') def post(self,request): print(request.POST) print("user :",end='') print(request.POST.get('user',None)) print("password :",end='') print(request.POST.get('password',None)) return HttpResponse('OK')
后臺(tái)接收到的是一個(gè)QueryDict,打印如下:
可以看到這里的數(shù)據(jù)是按照J(rèn)son的格式傳遞的,后臺(tái)也完美地進(jìn)行解析,但是,如果前端傳遞的數(shù)據(jù)為嵌套的Json,這種寫法就開始出現(xiàn)問(wèn)題!
2、解析嵌套的Json數(shù)據(jù)
前端代碼修改如下:
$.post("/login/", { "user":{ 'name':'threedog', 'age':18, 'sex':'男' }, "password":"123456" }, function (res) { console.log(res) });
這個(gè)時(shí)候后臺(tái)收到的東西就有意思了:
password取值正常,但是user沒能拿到值,而QueryDict的打印我們發(fā)現(xiàn),原本是嵌套的字典,現(xiàn)在全部由兩個(gè)鍵名合并成了新的鍵諸如:'user[sex]','user[age]'。這樣的鍵到了后臺(tái)是沒辦法按照普通字典或者json來(lái)進(jìn)行解析的。
上網(wǎng)查,說(shuō)是要使用request.raw_post_data代替request.POST就可以,然而很遺憾,報(bào)錯(cuò)再查之下發(fā)現(xiàn),raw_post_data在Django1.4版本之后被取消,我使用的是Django1.11。再往下查,知道了要使用request.body,還要通過(guò)simplejson來(lái)解析。
但是request.body的解析仍然不順利,前端不變,后臺(tái)直接打印request.body的結(jié)果如下:
一個(gè)包含了鍵值對(duì)兒的二進(jìn)制字符串,這個(gè)時(shí)候按網(wǎng)上的辦法使用simplejson.loads()解析會(huì)報(bào)錯(cuò):simplejson.errors.JSONDecodeError: Expecting value: line 1 column 1 (char 0)。不用在這個(gè)上面糾結(jié)了,simplejson直接解析不了這個(gè)body。
后來(lái)靈感突發(fā),發(fā)現(xiàn)前端在給出的數(shù)據(jù)原本就是JS中的object,并不是json的字符串,所以把前段的數(shù)據(jù)使用JSON.stringify()進(jìn)行轉(zhuǎn)換后,打印request.body以及通過(guò)simplejson.load()解析發(fā)現(xiàn)了令人驚喜的輸出:
到了這一步就基本不用說(shuō)啥了,完整接收了前端的json字符串并解析,這里如果不想安裝第三方庫(kù)simplejson的話,使用python自帶的json模塊也是可以解析的,只是在解析時(shí)需要將request.body進(jìn)行一次decode()即可。完整代碼如下
前端:
$.post("/login", JSON.stringify({ "user":{ 'name':'threedog', 'age':18, 'sex':'男' }, "password":"123456" }), function (res) { console.log(res) });
后臺(tái):
class Login(View): def get(self,request): return render(request,'login.html') def post(self,request): print(request.body) receive_data = simplejson.loads(request.body) print(receive_data) receive_data = json.loads(request.body.decode()) print(receive_data) return HttpResponse('OK')
程序輸出:
之前主要是因?yàn)閷懬岸私o數(shù)據(jù)的時(shí)候沒有使用JSON.stringify()進(jìn)行處理。導(dǎo)致后臺(tái)無(wú)論什么方法解析都是一團(tuán)糟。
3、簡(jiǎn)述應(yīng)用場(chǎng)景
這個(gè)應(yīng)用場(chǎng)景非常常見,除了我剛才提到的,前端給后臺(tái)的,是嵌套的json數(shù)據(jù)的情況。還有微信小程序給后臺(tái)數(shù)據(jù),也需要JSON.stringify()處理給json,還有安卓,IOS app訪問(wèn)網(wǎng)站后臺(tái)提交數(shù)據(jù),都需要這種方式傳值和解析。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
python讀寫文件write和flush的實(shí)現(xiàn)方式
今天小編就為大家分享一篇python讀寫文件write和flush的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-02-02python中sklearn的pipeline模塊實(shí)例詳解
這篇文章主要介紹了python中sklearn的pipeline模塊的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05Django結(jié)合ajax進(jìn)行頁(yè)面實(shí)時(shí)更新的例子
今天小編就為大家分享一篇Django結(jié)合ajax進(jìn)行頁(yè)面實(shí)時(shí)更新的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-08-08python中正則表達(dá)式findall的用法實(shí)例
在寫著自動(dòng)化測(cè)試的腳本時(shí)重新復(fù)習(xí)了一下正則表達(dá)式findall()方法,下面這篇文章主要給大家介紹了關(guān)于python中正則表達(dá)式findall用法的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09