范培忠 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,
//以下省略...
参考资料: