如何将表单的所有元素转换为JavaScript对象?
我希望有某种方法从表单自动构建JavaScript对象,而不必遍历每个元素。我不希望使用$('#formid').serialize();返回的字符串;,我也不希望$('#formid').serializeArray()返回映射;
如何将表单的所有元素转换为JavaScript对象?
我希望有某种方法从表单自动构建JavaScript对象,而不必遍历每个元素。我不希望使用$('#formid').serialize();返回的字符串;,我也不希望$('#formid').serializeArray()返回映射;
当前回答
更现代的方法是将reduce与serializeArray()一起使用,方法如下:
$('#formid').serializeArray()
.reduce((a, x) => ({ ...a, [x.name]: x.value }), {});
这将有助于许多“正常”情况。
对于具有重复名称属性的多个标记的非常常见的实例,这是不够的。
由于具有重复名称属性的输入通常位于某些“包装器”(div,ul,tr,…)内,如本示例所示:
<div class="wrapperClass">
<input type="text" name="one">
<input type="text" name="two">
</div>
<div class="wrapperClass">
<input type="text" name="one">
<input type="text" name="two">
</div>
可以使用reduce和map运算符对它们进行迭代:
$(".wrapperClass").map(function () {
return $(this).find('*').serializeArray()
.reduce((a, x) => ({ ...a, [x.name]: x.value }), {});
}).get();
结果将是以下格式的对象数组:
[
{
one: valueOfOne,
two: valueOfTwo
}, {
one: valueOfOne,
two: valueOfTwo
}
]
.get()运算符与map一起使用,以获得基本数组,而不是jQuery对象,这会产生更干净的结果。jQuery文档
其他回答
不使用JQuery序列化深度嵌套表单
在花了几天时间寻找这个没有依赖关系的问题的解决方案之后,我决定使用FormDataAPI制作一个非jQuery表单数据序列化程序。
序列化程序中的逻辑很大程度上基于jQuery插件jQueryBBQ中的de-param函数,然而,在这个项目中,所有依赖项都被删除了。
这个项目可以在NPM和Github上找到:
https://github.com/GistApps/deep-serialize-form
https://www.npmjs.com/package/deep-serialize-form
function deepSerializeForm(form) {
var obj = {};
var formData = new FormData(form);
var coerce_types = { 'true': !0, 'false': !1, 'null': null };
/**
* Get the input value from the formData by key
* @return {mixed}
*/
var getValue = function(formData, key) {
var val = formData.get(key);
val = val && !isNaN(val) ? +val // number
: val === 'undefined' ? undefined // undefined
: coerce_types[val] !== undefined ? coerce_types[val] // true, false, null
: val; // string
return val;
}
for (var key of formData.keys()) {
var val = getValue(formData, key);
var cur = obj;
var i = 0;
var keys = key.split('][');
var keys_last = keys.length - 1;
if (/\[/.test(keys[0]) && /\]$/.test(keys[keys_last])) {
keys[keys_last] = keys[keys_last].replace(/\]$/, '');
keys = keys.shift().split('[').concat(keys);
keys_last = keys.length - 1;
} else {
keys_last = 0;
}
if ( keys_last ) {
for (; i <= keys_last; i++) {
key = keys[i] === '' ? cur.length : keys[i];
cur = cur[key] = i < keys_last
? cur[key] || (keys[i+1] && isNaN(keys[i+1]) ? {} : [])
: val;
}
} else {
if (Array.isArray(obj[key])) {
obj[key].push( val );
} else if (obj[key] !== undefined) {
obj[key] = [obj[key], val];
} else {
obj[key] = val;
}
}
}
return obj;
}
window.deepSerializeForm = deepSerializeForm;
您可以这样做:
var frm = $(document.myform);
var data = JSON.stringify(frm.serializeArray());
请参见JSON。
所以我使用了公认的答案,发现了一个主要缺陷。它不支持以下输入数组:
<input type="checkbox" name="array[]" value="1"/>
<input type="checkbox" name="array[]" value="2"/>
<input type="checkbox" name="array[]" value="3"/>
这一小改动应该可以解决以下问题:
function objectifyForm(inp){
var rObject = {};
for (var i = 0; i < inp.length; i++){
if(inp[i]['name'].substr(inp[i]['name'].length - 2) == "[]"){
var tmp = inp[i]['name'].substr(0, inp[i]['name'].length-2);
if(Array.isArray(rObject[tmp])){
rObject[tmp].push(inp[i]['value']);
} else{
rObject[tmp] = [];
rObject[tmp].push(inp[i]['value']);
}
} else{
rObject[inp[i]['name']] = inp[i]['value'];
}
}
return rObject;
}
记住将$(this).serializeArray()的输出传递给它;否则它不会起作用。
我喜欢塞缪尔的版本,但我相信它有一个小错误。通常JSON发送为
{“coreSKU”:“PCGUYJS”,“name_de”:“whatever”,。。。
不作为
〔{“coreSKU”:“PCGUYJS”},{“name_de”:“whatever”},。。。
因此,功能IMO应为:
App.toJson = function( selector ) {
var o = {};
$.map( $( selector ), function( n,i )
{
o[n.name] = $(n).val();
});
return o;
}
并将其包装在数据数组中(正如通常预期的那样),最后将其作为跨页发送App.stringify({data:App.toJson(“#cropform:input”)})
对于精简版本,请参见问题3593046,对于所有可能的版本,请参阅json2.js。这应该涵盖了所有内容:)
serializeArray已经做到了这一点。您只需将数据转换为所需格式:
function objectifyForm(formArray) {
//serialize data function
var returnArray = {};
for (var i = 0; i < formArray.length; i++){
returnArray[formArray[i]['name']] = formArray[i]['value'];
}
return returnArray;
}
注意与实际输入同名的隐藏字段,因为它们会被覆盖。