JS序列化含动态输入的表单为JSON用于API调用(支持数组字段)
表单序列化为JSON通用实现方案
原函数仅支持点分隔的对象层级解析,未识别[index]格式的数组索引标记,因此会把数组项错误解析为带方括号的对象键。修改后的通用函数支持任意层级的对象、数组嵌套结构解析,可覆盖绝大多数表单序列化场景。
实现思路
- 解析表单字段名时,先将
[数字]格式的数组下标拆分为独立路径段,例如将Categories[0].Name拆分为路径段序列["Categories", "0", "Name"] - 逐层遍历路径段时,自动判断当前层级需要初始化的容器类型:如果下一级路径段为纯数字索引,则当前容器初始化为数组,否则初始化为对象
- 遍历到路径最后一段时,直接赋值对应表单值即可
完整实现代码
function formArrayConverter(formArray) { const result = {}; // 解析字段名,拆分对象键、数组索引为独立路径段 const parsePath = (nameStr) => { const segments = []; // 先按点拆分基础段 nameStr.split('.').forEach(segment => { // 匹配数组下标格式,将类似Categories[0]的段拆为Categories、0两个独立段 const arrayMatch = segment.match(/^(\w+)\[(\d+)\]$/); if (arrayMatch) { segments.push(arrayMatch[1]); segments.push(arrayMatch[2]); } else { segments.push(segment); } }); return segments; }; formArray.forEach(field => { const path = parsePath(field.name); let current = result; for (let i = 0; i < path.length; i++) { const key = path[i]; const isLast = i === path.length - 1; if (isLast) { current[key] = field.value; break; } // 下一个路径段为纯数字时,当前节点初始化为数组,否则初始化为对象 const nextKey = path[i+1]; const isNextArray = /^\d+$/.test(nextKey); if (!current[key]) { current[key] = isNextArray ? [] : {}; } current = current[key]; } }); return result; } // 调用示例 const myFormArray = $('#exampleForm').serializeArray(); const formJson = formArrayConverter(myFormArray); console.log(formJson);
兼容性说明
该实现支持各类复杂表单结构:
- 普通一级字段:比如
Id、EffectiveDate这类无嵌套字段 - 多层对象嵌套:比如
Manager.Name、User.Address.City这类点分隔的对象层级 - 数组嵌套结构:比如
Categories[0].Name这类包含数组索引的字段,支持数组内嵌套对象的常见业务场景 - 动态增减表单项:无论数组项数量多少,只要索引按数字顺序命名即可正确解析
如果需要对字段值做类型转换(比如把数字字符串转成Number类型、日期字符串转成时间戳),可以在最终赋值逻辑处增加类型判断处理即可。
输出效果
针对提供的测试表单,调用函数后将输出符合API要求的结构:
{ "Id": "32468", "EffectiveDate": "2022-06-03", "TotalAmount": "57.99", "Manager": { "Name": "ManagerName", "Level": "10" }, "Categories": [ {"Name": "Phone", "Amount": "47.99"}, {"Name": "Tax", "Amount": "10.00"} ] }
内容的提问来源于stack exchange,提问作者Heliospeed
相关产品推荐
相关产品推荐

