同一页面第一次提交成功、第二次却报 JSON 解析错误,先检查提交对象是否被复用。FormData.append 是追加,不会替换旧值;对象一直保留时,同名字段可能在第二次提交中出现多次。
用 getAll 直接看到累积
const form = new FormData();
form.append("items", JSON.stringify([{ id: 1 }]));
form.append("items", JSON.stringify([{ id: 2 }]));
console.log(form.getAll("items"));
结果中有两个字符串值。它们各自可以是合法 JSON,但服务端如何绑定重复字段取决于接口和框架;可能读取一个值、多个值或经过其他转换,不能直接把重复字段定义成一个必然非法的 JSON 文本。append 与 set 的区别
旧记录在重复提交时出现解析异常,重新创建 FormData 后恢复。这个处理符合“旧数据累积”的方向,但定位时仍应查看实际请求,而不是只根据异常中的一个字符判断。
每次请求创建一个表单对象
function createRequestForm(items) {
const form = new FormData();
form.append("items", JSON.stringify(items));
return form;
}
const firstRequest = createRequestForm([{ id: 1 }]);
const secondRequest = createRequestForm([{ id: 2 }]);
console.log(firstRequest.getAll("items").length); // 1
console.log(secondRequest.getAll("items").length); // 1
这种方式把表单生命周期与一次请求对齐,避免上次提交残留。若业务确实要复用对象,而且字段只有一个值,可使用 set 替换;上传多文件等真正需要同名多值的场景则应保留 append。
不要只在请求结束后清空共享对象:快速连续点击时,两个请求可能同时操作它。还要检查业务数组是否反复 push,以及重试逻辑有没有再次追加。
验证前后端契约一致
先观察第一次和第二次请求中的字段名称、数量及内容;再看后台形参是字符串、集合还是 JSON 请求体。浏览器调试面板显示“有 items”,不等于后端已经收到了预期类型。
对象数组如何与 Spring Boot 明确约定,见FormData 列表与显式反序列化。修复应以重复提交时仍只包含本次数据为准,而不是让解析器忽略多余内容。