Express中如何从req.body获取表单提交的嵌套对象数组数据?
问题根源
- body-parser的
extended参数配置错误:当参数为false时,body-parser使用底层的querystring库解析表单数据,仅支持解析扁平结构的键值对,无法识别嵌套对象、数组这类复杂结构;你设置为false后得到的带完整路径的键名,就是没有被合并成嵌套结构的原始解析结果。 - 之前拿到平铺字符串数组的情况,是前端表单input的name属性配置有误,所有invoiceRows下的字段都统一用了
invoiceRows作为name,导致所有值被合并成了一个一维数组。 - 额外代码问题:路由中
let invoice = new Invoice(); invoice = req.body;的写法是错误的,会直接覆盖掉你创建的Mongoose模型实例,完全丢失模型的方法和校验能力。
具体解决步骤
- 调整body-parser配置
把你项目中body-parser的urlencoded解析配置修改为extended: true,示例代码:
// 原来的app.use(bodyParser.urlencoded({ extended: false }))改成下面的 app.use(bodyParser.urlencoded({ extended: true })) // 如果是Express 4.16+版本,内置了express.urlencoded,也可以直接写 app.use(express.urlencoded({ extended: true }))
这个配置会使用qs库解析表单数据,自动把invoiceRows[0].productTitle这类键名合并成嵌套的对象数组结构,直接就能拿到符合你Schema要求的invoiceRows字段。
确认前端表单字段的name属性格式
你提交的表单中,invoiceRows对应的输入框name属性要严格按照索引+字段名的格式书写,比如第一条明细的商品名称输入框name为invoiceRows[0].productTitle,单价为invoiceRows[0].unitPrice,第二条对应为invoiceRows[1].productTitle、invoiceRows[1].unitPrice,依次类推即可。修正路由中的模型实例化写法
不要直接覆盖模型实例,正确的写法是把req.body作为参数传入模型构造函数,或者用扩展运算符合并属性:
invoiceRouter.post('/', async (req,res) => { console.log(req.body); // 此时打印就可以看到嵌套结构的invoiceRows数组 // 直接把请求数据传入构造函数 let invoice = new Invoice({ ...req.body, status: 0 }); // 调用save方法保存到数据库,这里记得补充错误处理逻辑 await invoice.save(); res.redirect('/invoices'); });
内容的提问来源于stack exchange,提问作者priitpätt
相关产品推荐
相关产品推荐

