JavaScript使用serializeObject实现表单嵌套数组序列化问题求助
解决方案
有两种实现方式,可根据实际需求选择:
方案1:调整input的name属性 + 升级serializeObject支持嵌套解析
该方案通用性更强,后续其他嵌套表单场景也可直接复用升级后的序列化方法。
- 先修改动态生成表单的代码,调整input的name属性为两层数组结构:
var resourceRatioBoxTag = new Array(); for (var i = 0; i < selectedData.resource_ratio.length; i++) { resourceRatioBoxTag[i] = "<p id='resourceRatio[" + i + "]' name='resourceRatio'>"; for (var j = 0; j < selectedData.resource_ratio[i].length; j++) { // 仅修改name属性的定义即可 resourceRatioBoxTag[i] += "<input type='text' id='resourceRatio[" + i + "][" + j + "]' value='" + selectedData.resource_ratio[i][j] + "' name='resourceRatio[" + i + "][]'>"; } resourceRatioBoxTag[i] += "</p>"; $("#resourceRatioDiv").append(resourceRatioBoxTag[i]); }
- 替换原有serializeObject方法,升级为支持嵌套结构解析的版本:
$.fn.serializeObject = function() { var o = {}; var a = this.serializeArray(); // 正则用于解析name里的多层键/索引 var reg = /([^\[\]]+)(?:\[([^\[\]]*)\])?/g; $.each(a, function() { var name = this.name; var value = this.value || ''; var current = o; var match, keys = []; // 拆解name的所有层级键 while ((match = reg.exec(name)) !== null) { keys.push(match[1]); if (match[2] !== undefined) keys.push(match[2]); } reg.lastIndex = 0; // 逐层构建嵌套结构 for (var i = 0; i < keys.length; i++) { var key = keys[i]; var nextKey = keys[i + 1]; if (i === keys.length - 1) { // 最后一层赋值 if (Array.isArray(current)) { current.push(value); } else { if (current[key] !== undefined) { if (!Array.isArray(current[key])) { current[key] = [current[key]]; } current[key].push(value); } else { current[key] = value; } } } else { // 下一层是数字索引则创建数组,否则创建对象 if (!current[key]) { current[key] = isNaN(nextKey) ? {} : []; } current = current[key]; } } }); // 映射为你需要的resource_ratio键名,且转换第二组数据为数字类型,不需要可删除这段 if (o.resourceRatio) { o.resource_ratio = o.resourceRatio; delete o.resourceRatio; o.resource_ratio[1] = o.resource_ratio[1].map(Number); } return o; };
方案2:不改动现有代码,直接后处理序列化结果
如果不想修改原有表单生成逻辑和序列化方法,可对现有输出的扁平结果做二次处理:
// 先调用原有方法得到扁平结构结果 var rawResult = $('form').serializeObject(); // 直接转换为目标结构 var targetResult = { resource_ratio: Object.values(rawResult).map((item, index) => { // 第二组为数值类型,做格式转换,不需要可直接返回item return index === 1 ? item.map(Number) : item; }) };
该方案改造成本最低,你之前尝试用Object.values未生效,只是缺少了索引对应的格式转换和键名映射步骤,补上即可正常使用。
内容的提问来源于stack exchange,提问作者user16535642
相关产品推荐
相关产品推荐

