如何将动态表单序列化后的JavaScript对象转换为数组?
动态表单字段序列化后的结构转换
问题场景
我有一个通过JavaScript动态生成字段的表单,HTML结构如下:
<input type="text" name="item[0][name]" /> <input type="text" name="item[0][email]" /> <input type="text" name="item[0][address]" /> <input type="text" name="item[1][name]" /> <input type="text" name="item[1][email]" /> <input type="text" name="item[1][address]" /> <input type="text" name="item[2][name]" /> <input type="text" name="item[2][email]" /> <input type="text" name="item[2][address]" />
提交表单时,我用下面的JavaScript函数获取值:
var obj = serializeObject(form) function serializeObject(form) { var o = {}; var a = form.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 || ''; } }); return o; };
得到的是扁平结构的对象:
var obj = { 'item[0][name]':'a', 'item[0][email]':'a1', 'item[0][address]':'a2', 'item[1][name]':'b', 'item[1][email]':'b1', 'item[1][address]':'b2', 'item[2][name]':'c', 'item[2][email]':'c1', 'item[2][address]':'c2', }
我希望把它转换成嵌套数组结构:
var arr = [ {name:'a', email:'a1', address:'a2'}, {name:'b', email:'b1', address:'b2'}, {name:'c', email:'c1', address:'c2'} ]
请问不使用硬编码的方式,最佳的转换方法是什么?
解决方案
方法一:修改序列化函数直接生成目标结构
相比先得到扁平对象再转换,直接在序列化阶段构建目标结构更高效。我们可以解析每个字段的name属性,提取索引和字段名,然后组装成数组:
function serializeToItemsArray(form) { const items = []; const fields = form.serializeArray(); fields.forEach(field => { // 匹配item[索引][字段名]的命名结构 const match = field.name.match(/item\[(\d+)\]\[(\w+)\]/); if (match) { const index = parseInt(match[1], 10); const key = match[2]; // 初始化对应索引的对象 if (!items[index]) { items[index] = {}; } items[index][key] = field.value || ''; } }); // 过滤可能的空项(适配索引不连续的情况) return items.filter(item => item); } // 使用示例 var arr = serializeToItemsArray(form);
方法二:转换已有的扁平对象
如果已经拿到了扁平结构的obj,可以遍历其键值对,通过正则解析后组装成目标数组:
function convertToItemsArray(obj) { const items = []; Object.entries(obj).forEach(([key, value]) => { const match = key.match(/item\[(\d+)\]\[(\w+)\]/); if (match) { const index = parseInt(match[1], 10); const prop = match[2]; if (!items[index]) { items[index] = {}; } items[index][prop] = value; } }); return items.filter(item => item); } // 使用示例 var arr = convertToItemsArray(obj);
说明
两种方法都通过正则解析字段命名规则,不需要硬编码具体字段名(比如name、email),能适配所有遵循item[索引][字段名]规则的动态字段。如果后续表单字段命名规则调整,只需要修改正则表达式即可。
内容的提问来源于stack exchange,提问作者Toniq
相关产品推荐
相关产品推荐

