1. 程式人生 > >Form表單自動轉JSON物件、及解決AJAX呼叫時JSON物件陣列成員key被修改問題

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,
    //以下省略...

  參考資料: