Node.js API向MongoDB写入数据时触发必填字段验证报错
问题根因
你遇到的必填字段校验报错,核心原因是服务端没有正确解析到请求体里的JSON参数:
Postman、Thunder Client这类工具发JSON请求时会自动带上Content-Type: application/json请求头,你写的JS测试脚本、Flutter端发请求时默认没加这个头,导致Express的express.json()中间件不会解析请求体,req.body为空对象,解构出来的name/email/password全是undefined,自然触发Mongoose的必填字段校验。
另外你贴的服务端代码本身还有两个会导致异常的硬伤:
- 拼写错误:bcrypt生成哈希值的变量名是
hashedPassword,创建User实例时错写成了hashePassword,少了一个d,就算请求体解析正常,这里也会导致password字段传空。 - 响应顺序错误:还没执行
user.save()存库就提前调用res.json()返回响应,后续数据库操作抛错时无法被路由层捕获,直接触发你看到的UnhandledPromiseRejectionWarning。
修复步骤
1. 修复服务端代码
补全异常捕获、修正拼写错误、调整响应顺序,修复后的参考代码如下:
const DB = "mydburl" // 补全你自己的依赖引入、端口配置 // const express = require('express') // const bcryptjs = require('bcryptjs') // const mongoose = require('mongoose') // const User = require('./models/User') // 替换为你实际的User模型路径 // const PORT = 3000 const app = express() app.use(express.json()) app.post('/api/signup', async (req, res) => { try { const {name, email, password} = req.body // 调试阶段可以打开下面这行日志,确认请求体是否正常解析 // console.log('收到请求体:', req.body) const existingUser = await User.findOne({ email }) if (existingUser) { return res.status(400).json({ msg: "同邮箱用户已存在" }) } const hashedPassword = await bcryptjs.hash(password, 8) // 修复拼写错误 let user = new User({ email, password: hashedPassword, name, }) // 先执行存库操作,成功后再返回响应 user = await user.save() console.log('用户创建成功:', user) return res.json(user) } catch (err) { // 统一捕获异常,避免出现未处理的Promise拒绝 console.error('注册接口报错:', err) return res.status(500).json({ msg: "服务器处理失败", error: err.message }) } }) mongoose.connect(DB) .then(() => console.log("数据库连接成功")) .catch(e => console.log('数据库连接失败:', e)) app.listen(PORT, "0.0.0.0", () => { console.log(`服务启动,监听端口 ${PORT}`) })
2. 修正客户端请求配置
所有非接口测试工具发起的请求,都需要手动配置JSON请求头:
- JS测试脚本如果用原生fetch,需要加
headers: {'Content-Type': 'application/json'},同时用JSON.stringify()把参数对象转成JSON字符串作为请求体传入;如果用axios,默认会带JSON头,检查下是不是手动改了请求体格式。 - Flutter端不管用
http包还是dio包,都要设置请求头Content-Type: application/json,传参时先将Dart的Map对象通过jsonEncode()转成JSON字符串再放入请求体,不要直接传原生对象。
验证方式
服务端启动后先发起一次测试请求,看控制台打印的请求体日志,如果能正确拿到你传的三个字段值,就说明解析逻辑正常,后续不会再触发必填字段校验报错。
内容的提问来源于stack exchange,提问作者Ammar Mohib
相关产品推荐
相关产品推荐

