轉載至:http://www.cnblogs.com/lianer/p/5178693.html
接觸nodejs已有一段時間了,但最近才開始落實項目,於是使用express應用生成器生成了一個應用。開發過程中發現ajax提交的數據無法被express正確的解析,主要的情況是這樣的:
// 瀏覽器端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' } });
顯然這樣的解析結果是不能直接拿來用的,莫名其妙的一個坑,困了我許久。
bodyParser中間件
bodyParser中間件用來解析http請求體,是express默認使用的中間件之一。
使用express應用生成器生成一個網站,它默認已經使用了 bodyParser.json 與 bodyParser.urlencoded 的解析功能,除了這兩個,bodyParser還支持對text、raw的解析。
app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false }));
顧名思義,bodyParser.json是用來解析json數據格式的。bodyParser.urlencoded則是用來解析我們通常的form表單提交的數據,也就是請求頭中包含這樣的信息: Content-Type: application/x-www-form-urlencoded
常見的四種Content-Type類型:
- application/x-www-form-urlencoded 常見的form提交
- multipart/form-data 文件提交
- application/json 提交json格式的數據
- text/xml 提交xml格式的數據
詳細解讀 urlencoded
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介紹
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' ] } });