如何将表单的所有元素转换为JavaScript对象?
我希望有某种方法从表单自动构建JavaScript对象,而不必遍历每个元素。我不希望使用$('#formid').serialize();返回的字符串;,我也不希望$('#formid').serializeArray()返回映射;
如何将表单的所有元素转换为JavaScript对象?
我希望有某种方法从表单自动构建JavaScript对象,而不必遍历每个元素。我不希望使用$('#formid').serialize();返回的字符串;,我也不希望$('#formid').serializeArray()返回映射;
当前回答
使用maček的解决方案,我对其进行了修改,使其与ASP.NET MVC在同一表单上处理嵌套/复杂对象的方式一致。您所要做的就是将验证部分修改为:
"validate": /^[a-zA-Z][a-zA-Z0-9_]*((?:\[(?:\d*|[a-zA-Z0-9_]+)\])*(?:\.)[a-zA-Z][a-zA-Z0-9_]*)*$/,
这将匹配并正确映射具有以下名称的元素:
<input type="text" name="zooName" />
And
<input type="text" name="zooAnimals[0].name" />
其他回答
我发现Tobias Cohen的代码有一个问题(我没有足够的分数来直接评论它),否则它对我来说是有效的。如果您有两个同名的选择选项,都是value=“”,原始代码将生成“name”:“”而不是“name”:[”,“”]
我认为这可以通过在第一个if条件中添加“||o[this.name]==''”来解决:
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] || o[this.name] == '') {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
我的库phery中的代码有一个序列化例程,可以处理非常复杂的表单(如演示中所示https://github.com/pocesar/phery/blob/master/demo.php#L1664),而且不是一刀切。它实际上检查每个字段的类型。例如,单选框与范围不同,与keygen不同,与select multiple不同。我的功能涵盖了这一切,你可以看到它在https://github.com/pocesar/phery/blob/master/phery.js#L1851.
serializeForm:function (opt) {
opt = $.extend({}, opt);
if (typeof opt['disabled'] === 'undefined' || opt['disabled'] === null) {
opt['disabled'] = false;
}
if (typeof opt['all'] === 'undefined' || opt['all'] === null) {
opt['all'] = false;
}
if (typeof opt['empty'] === 'undefined' || opt['empty'] === null) {
opt['empty'] = true;
}
var
$form = $(this),
result = {},
formValues =
$form
.find('input,textarea,select,keygen')
.filter(function () {
var ret = true;
if (!opt['disabled']) {
ret = !this.disabled;
}
return ret && $.trim(this.name);
})
.map(function () {
var
$this = $(this),
radios,
options,
value = null;
if ($this.is('[type="radio"]') || $this.is('[type="checkbox"]')) {
if ($this.is('[type="radio"]')) {
radios = $form.find('[type="radio"][name="' + this.name + '"]');
if (radios.filter('[checked]').size()) {
value = radios.filter('[checked]').val();
}
} else if ($this.prop('checked')) {
value = $this.is('[value]') ? $this.val() : 1;
}
} else if ($this.is('select')) {
options = $this.find('option').filter(':selected');
if ($this.prop('multiple')) {
value = options.map(function () {
return this.value || this.innerHTML;
}).get();
} else {
value = options.val();
}
} else {
value = $this.val();
}
return {
'name':this.name || null,
'value':value
};
}).get();
if (formValues) {
var
i,
value,
name,
$matches,
len,
offset,
j,
fields;
for (i = 0; i < formValues.length; i++) {
name = formValues[i].name;
value = formValues[i].value;
if (!opt['all']) {
if (value === null) {
continue;
}
} else {
if (value === null) {
value = '';
}
}
if (value === '' && !opt['empty']) {
continue;
}
if (!name) {
continue;
}
$matches = name.split(/\[/);
len = $matches.length;
for (j = 1; j < len; j++) {
$matches[j] = $matches[j].replace(/\]/g, '');
}
fields = [];
for (j = 0; j < len; j++) {
if ($matches[j] || j < len - 1) {
fields.push($matches[j].replace("'", ''));
}
}
if ($matches[len - 1] === '') {
offset = assign_object(result, fields, [], true, false, false);
if (value.constructor === Array) {
offset[0][offset[1]].concat(value);
} else {
offset[0][offset[1]].push(value);
}
} else {
assign_object(result, fields, value);
}
}
}
return result;
}
它是我的库phery的一部分,但可以移植到您自己的项目中。它在应该有数组的地方创建数组,从select、normalize复选框等选项中获取正确的选择选项。如果要将其转换为JSON(真正的JSON字符串),只需执行JSON.stringify($('form').serializeForm());
我检查了所有其他答案是否存在问题,如果输入名称是数组,例如name[key],那么应该这样生成:
名称:{key:value}
例如:如果您的HTML表单与下面的表单类似:
<form>
<input name="name" value="value" >
<input name="name1[key1]" value="value1" >
<input name="name2[key2]" value="value2" >
<input name="name3[key3]" value="value3" >
</form>
但是它应该像下面的JSON一样生成,而不是像下面这样的对象和所有其他答案。因此,如果有人想带来类似以下JSON的内容,请尝试下面的JS代码。
{
name : 'value',
name1 : { key1 : 'value1' },
name2 : { key2 : 'value2' },
name3 : { key2 : 'value2' }
}
$.fn.getForm2obj=函数(){var_={};$.map(this.serializeArray(),函数(n){常量键=n.name.match(/[a-zA-Z0-9_]+|(?=\[\])/g);如果(按键长度>1){让tmp=_;pop=keys.pop();for(设i=0;i<keys.length,j=keys[i];i++){tmp[j]=(!tmp[j]?(pop=='')?[]:{}:tmp[j]),tmp=tmp[j];}如果(pop=='')tmp=(!Array.isArray(tmp)?[]:tmp)、tmp.push(n.value);否则tmp[pop]=n.value;}else_[keys.pop()]=n.value;});返回_;}console.log($('form').getForm2obj());$('form input').change(函数(){console.clear();console.log($('form').getForm2obj());});<script src=“https://code.jquery.com/jquery-3.2.1.min.js“></script><表单><input name=“name”value=“value”><input type=“checkbox”name=“name1[]”value=“1”checked=“checked”>1<input type=“checkbox”name=“name1[]”value=“2”>2<input-type=“checkbox”name=“name1[]”value=“3”>3<br><input-type=“radio”name=“gender”value=“male”checked=“checked”>男性<input-type=“radio”name=“gender”value=“female”>女性<input name=“name2[key1]”value=“value1”><input name=“一个[另一个][另一个]”value=“value4”><input name=“name3[1][name]”value=“value4”><input name=“name3[2][name]”value=“value4”><input name=“[]”value=“value5”></form>
Tobias Cohen解决方案的固定版本。此函数正确处理0和“”等错误值。
jQuery.fn.serializeObject = function() {
var arrayData, objectData;
arrayData = this.serializeArray();
objectData = {};
$.each(arrayData, function() {
var value;
if (this.value != null) {
value = this.value;
} else {
value = '';
}
if (objectData[this.name] != null) {
if (!objectData[this.name].push) {
objectData[this.name] = [objectData[this.name]];
}
objectData[this.name].push(value);
} else {
objectData[this.name] = value;
}
});
return objectData;
};
以及一个CoffeeScript版本,方便您编写代码:
jQuery.fn.serializeObject = ->
arrayData = @serializeArray()
objectData = {}
$.each arrayData, ->
if @value?
value = @value
else
value = ''
if objectData[@name]?
unless objectData[@name].push
objectData[@name] = [objectData[@name]]
objectData[@name].push value
else
objectData[@name] = value
return objectData
好的,我知道这个问题已经有了一个高票的答案,但最近又有人问了一个类似的问题,我也被导向这个问题。我也想提供我的解决方案,因为它比公认的解决方案有一个优势:可以包含禁用的表单元素(这有时很重要,取决于UI的功能)
以下是我对另一个SO问题的回答:
最初,我们使用的是jQuery的serializeArray()方法,但这不包括禁用的表单元素。我们通常会禁用与页面上其他源“同步”的表单元素,但我们仍然需要在序列化对象中包含数据。因此serializeArray()已过时。我们使用:input选择器获取给定容器中的所有输入元素(启用和禁用),然后使用$.map()创建对象。
var inputs = $("#container :input");
var obj = $.map(inputs, function(n, i)
{
var o = {};
o[n.name] = $(n).val();
return o;
});
console.log(obj);
请注意,要使其工作,每个输入都需要一个name属性,该属性将是生成对象的属性的名称。
这实际上与我们使用的略有不同。我们需要创建一个结构化为.NET IDictionary的对象,所以我们使用了这个:(我在这里提供它,以防有用)
var obj = $.map(inputs, function(n, i)
{
return { Key: n.name, Value: $(n).val() };
});
console.log(obj);
我喜欢这两种解决方案,因为它们都是$.map()函数的简单用法,并且您可以完全控制选择器(因此,您最终会在结果对象中包含哪些元素)。此外,不需要额外的插件。普通的旧jQuery。