Form表單自動轉JSON物件、及解決AJAX呼叫時JSON物件陣列成員key被修改問題
範培忠 2018-05-11
本文講解如何定義一個通用方法實現form表單內容自動打包成JSON物件用於AJAX提交,以及當form表單有checkbox時,該JSON物件會擁有一個成員陣列提交到後臺後會被“篡改”的問題(key name會被自動加一箇中括號[]),JSON物件如下:
{"id":"998", "name":["臀部不放鬆","入定","雜念多"],"name2":["adsfasfas","2342 34r 23r"]),"option":"Option two"}
一、form轉JSON物件通用方法
我們一般可以使用serializeArray()來組裝用於AJAX提交的JSON物件。常見的寫法如下:
function serializeFormToJSON() {
formObject = {};
x = $("form").serializeArray();
$.each(x, function (i, field) {
formObject[field.name] = field.value;
});
return formObject;
}
但是如果當form表單裡有一組checkbox或redio時會發生覆蓋,我們需要將一組checkbox或redio的值序列化成陣列物件。
此外,還要在checkbox或radio沒有任何選擇時,生成一個空值,否則容易導致後端獲取資料時報錯。
優化的寫法如下:
$.fn.serializeObject = function () { var o = {}; var a = this.serializeArray(); $.each(a, function () { if (o[this.name] !== undefined) { if (!o[this.name].push) { o[this.name] = [o[this.name]]; } o[this.name].push(this.value || ''); } else { o[this.name] = this.value || ''; } }); var $radio = $('input[type=radio],input[type=checkbox]',this); $.each($radio,function(){ if(!o.hasOwnProperty(this.name)){ o[this.name] = ''; } }); return o; };
可以使用如下方式訪問:
function prepareForm() {
var obj = $("form").serializeObject();
console.log(obj);
}
實際效果就是這樣(name和name2是兩組checkbox,option是一組radio):
用字串形式表示該JSON物件就是本文開頭的那個形式:
{"id":"較舒服", "name":["臀部不放鬆","入定","雜念多"],"name2":["adsfasfas","2342 34r 23r"]),"option":"Option two"}
那麼此時使用AJAX設定為data直接上傳就會出現詭異的問題。
二、JSON物件陣列成員AJAX提交到後臺key被“篡改”問題的解決
為什麼說JSON物件陣列成員在使用AJAX提交到後臺後,key會被“篡改”呢,如下圖所示:
我在控制器方法上打了個斷點,可以看見傳入的JSON字串,key為“name”的鍵值對已經被篡改成了key為“name[]”,增加一對中括號,導致按名稱解析引數時無法正確地獲取資訊。
這也就是AJAX呼叫組織資料是,只要遇到有checkbox時(checkbox的多選值會被處理成一個數組成員)就需要單獨進行stringify的原因,不然就會出錯。已然形成“潛規則”。一般的寫法如下:
data: {"id":"較舒服", "name":JSON.stringify(["臀部不放鬆","入定","雜念多"]),"name2":JSON.stringify(["adsfasfas","2342 34r 23r"]),"option":"Option two"},
至於解決方法也很簡單,jQuery的AJAX方法還有一項屬性叫做traditional,將它設定為true就可以避免JSON陣列的深度序列化。就不用單獨對陣列呼叫stringify了。
$.ajax({
type: "post",
traditional:true,
//以下省略...
參考資料: