Express服务端req.body返回异常字符串 无法解析JSON请求参数
问题现象
在基于Express框架的Node.js服务端中调用req.body时,返回格式异常的字符串,而非预期的JSON对象,无法直接读取客户端传递的参数。
复现代码
客户端实现
客户端通过Axios向http://localhost:4000/signup接口发起POST请求,提交表单中的用户名、邮箱、密码字段,代码如下:
const handleSubmit = async e => { e.preventDefault(); const url = "http://localhost:4000/signup"; var credentials = JSON.stringify({ "username": e.target[0].value, "email": e.target[1].value, "password": e.target[2].value }) const config: AxiosRequestConfig = { method: 'post', url: url, data: credentials, headers: { 'Content-Type': 'application/x-www-form-urlencoded', } } console.log('@singup credentials:', credentials) // <----- 客户端侧打印日志 try { const resp = await axios(config) console.log('data:',resp.data); } catch (err) { // 错误处理 console.log('at signup post error:') console.error(err); } }
服务端实现
服务端已提前配置bodyParser中间件支持请求体解析:
app.use(bodyParser.json()); // 支持JSON格式编码请求体 app.use(bodyParser.urlencoded({ extended: true })); // 支持urlencoded格式编码请求体
/signup接口处理代码如下:
app.route("/signup") .post((req, res) => { console.log("req.body:") console.log(req.body) // <----- 服务端侧打印日志 var user = new User({ username: req.body.username, email: req.body.email, password: req.body.password, }); user.save((err, docs) => { if (err) { console.log('signup POST req fail from /signup endpoint') res.send("error in signpu post") } else { req.session.user = docs; res.redirect("/dashboard"); } }); });
实际运行表现
服务端打印的req.body为异常格式字符串,无法读取username、email、password等字段。
问题解答
- 服务端无法获取结构化
req.body的核心原因是请求头声明的内容编码类型和实际传入的请求体格式完全不匹配。
当前手动设置的请求头Content-Type: application/x-www-form-urlencoded要求请求体必须是参数名1=参数值1&参数名2=参数值2的URL键值对拼接格式,但实际传给接口的是JSON.stringify()生成的JSON格式字符串,body-parser的urlencoded解析器按照urlencoded规则拆解不符合格式的内容,自然无法生成结构化的对象,只能拿到异常字符串。
该场景不需要额外做自定义编解码,只要统一前后端传参格式,即可直接通过req.body.username读取参数,两种可选方案:- 走JSON格式传参:把请求头的
Content-Type改为application/json,保留现有JSON.stringify序列化参数对象的逻辑即可,服务端配置的bodyParser.json()中间件会自动完成解析,生成可直接读取属性的JS对象。 - 走form-urlencoded格式传参:去掉
JSON.stringify操作,不要直接传原始JS对象,用原生URLSearchParams拼接参数,或者用qs库把参数对象序列化成key=val&key2=val2格式的字符串,匹配application/x-www-form-urlencoded的格式要求,服务端的bodyParser.urlencoded()中间件就能正常解析。
- 走JSON格式传参:把请求头的
- 客户端添加或移除
JSON.stringify序列化操作均不改变异常现象的表现完全符合预期。
只要保留手动写死的Content-Type: application/x-www-form-urlencoded请求头,两种写法都会出现格式不匹配问题:- 保留
JSON.stringify时,传入的是JSON结构字符串,不符合urlencoded要求的键值对拼接格式,解析失败。 - 去掉
JSON.stringify直接把原始JS对象传给Axios的data字段,Axios默认会自动将JS对象序列化为JSON字符串,同时自动把Content-Type设为application/json,但手动强制覆盖Content-Type为urlencoded类型后,依然会出现请求头声明格式和实际内容格式不匹配的问题,解析还是失败。
- 保留
内容的提问来源于stack exchange,提问作者Awshaf Ishtiaque
相关产品推荐
相关产品推荐

