接觸nodejs已有一段時間了,但最近纔開始落實項目,因而使用express應用生成器生成了一個應用。開發過程當中發現ajax提交的數據沒法被express正確的解析,主要的狀況是這樣的:javascript
// 瀏覽器端post一個對象 $.ajax({ url: "/save", type: "post", data: { name: "henry", age: 30, hobby: [ "sport", "coding" ] } }); // express接收這個對象 router.post("/save", function (req, res, next) { console.log(req.body); // => { 'info[name]': 'henry','info[age]': '30','hobby[1]': 'sport','hobby[2]': 'coding' } });
顯然這樣的解析結果是不能直接拿來用的,莫名其妙的一個坑,困了我許久。java
bodyParser中間件用來解析http請求體,是express默認使用的中間件之一。node
使用express應用生成器生成一個網站,它默認已經使用了 bodyParser.json
與 bodyParser.urlencoded
的解析功能,除了這兩個,bodyParser還支持對text、raw的解析。jquery
app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false }));
顧名思義,bodyParser.json是用來解析json數據格式的。bodyParser.urlencoded則是用來解析咱們一般的form表單提交的數據,也就是請求頭中包含這樣的信息: Content-Type: application/x-www-form-urlencoded
git
常見的四種Content-Type類型:github
application/x-www-form-urlencoded
常見的form提交ajax
multipart/form-data
文件提交express
application/json
提交json格式的數據json
text/xml
提交xml格式的數據數組
bodyParser.urlencoded
模塊用於解析req.body的數據,解析成功後覆蓋原來的req.body,若是解析失敗則爲 {}
。該模塊有一個屬性extended,官方介紹以下:
The extended option allows to choose between parsing the URL-encoded data with the querystring library (when false) or the qs library (when true). Defaults to true, but using the default has been deprecated.
大體的意思就是:extended選項容許配置使用querystring(false)或qs(true)來解析數據,默認值是true,但這已是不被同意的了。
querystring就是nodejs內建的對象之一,用來字符串化對象或解析字符串。如
querystring.parse("name=henry&age=30") => { name: 'henry', age: '30' }
那麼,既然querystring已經能完成對urlencode的解析了,爲何還須要qs?qs又是什麼?
qs是一個querystring的庫,在qs的功能基礎上,還支持更多的功能並優化了一些安全性。好比,對象解析的支持:
// 內建對象 querystring querystring.parse("info[name]=henry&info[age]=30&hobby[1]=sport&hobby[2]=coding") => { 'info[name]': 'henry', 'info[age]': '30', 'hobby[1]': 'sport', 'hobby[2]': 'coding' } // 第三方插件 qs qs.parse("info[name]=henry&info[age]=30&hobby[1]=sport&hobby[2]=coding") => { info: { name: 'henry', age: '30' }, hobby: [ 'sport', 'coding' ] }
能夠看出,querystring並不能正確的解析複雜對象(多級嵌套),而qs卻能夠作到。
可是qs也不是萬能的,對於多級嵌套的對象,qs只會解析5層嵌套,超出的部分會表現的跟本文頭部的那種狀況同樣;對於數組,qs最大隻會解析20個索引,超出的部分將會以鍵值對的形式解析。
做爲一箇中間件,qs必需要爲性能考慮,纔會有如此多的限制,express也默認使用qs來解析請求體。
理論上來講,form表單提交不會有多級嵌套的狀況,而urlencoded自己也是form的內容類型,所以,bodyParser.urlencoded不支持多級嵌套也是很合理的設計。
那麼,若是咱們非要上傳一個十分複雜的對象,應該怎麼辦?
出現這個問題的根本緣由是:我以form的形式去提交了一個json數據。
jquery默認的 content-Type
配置的是 application/x-www-form-urlencoded
,
所以更改ajax請求參數:contentType: "application/json"
,並將數據轉成json提交,問題就解決了。
// 瀏覽器端post一個對象 $.ajax({ url: "/save", type: "post", contentType: "application/json", data: JSON.stringify({ name: "henry", age: 30, hobby: [ "sport", "coding" ] }) }); // express接收這個對象 router.post("/save", function (req, res, next) { console.log(req.body); // => { name: 'henry', age: 30, hobby: [ 'sport', 'coding' ] } });
大多時候,咱們只知道如何去使用,而不知道爲何這麼用。