You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js/Express中捕获并使用格式错误的JSON POST请求及路由级错误中间件不生效问题

Node.js/Express中捕获并使用格式错误的JSON POST请求及路由级错误中间件不生效问题

我来帮你拆解并解决这两个问题:


一、处理格式不标准的JSON请求

你遇到的核心问题是:请求头标了application/json,但body是不符合严格JSON规范的(比如键没有双引号的{ something: "data" }),而Express默认的express.json()中间件只支持严格JSON解析,所以会抛出语法错误。

这里有两种靠谱的解决思路:

1. 使用宽松JSON解析库(推荐)

可以用json5这个库,它支持无引号键、单引号字符串等宽松格式的JSON解析。步骤如下:

  • 先安装依赖:npm install json5
  • 替换默认的JSON解析中间件,用自定义逻辑读取原始body并解析:
const express = require('express');
const JSON5 = require('json5');
const router = express.Router();

// 自定义中间件:处理宽松格式的JSON
router.use((req, res, next) => {
  // 只处理Content-Type为application/json的请求
  if (req.headers['content-type']?.includes('application/json')) {
    let rawBody = '';
    // 读取原始请求body
    req.on('data', chunk => rawBody += chunk);
    req.on('end', () => {
      try {
        // 用JSON5解析宽松格式
        req.body = JSON5.parse(rawBody);
        next();
      } catch (err) {
        // 解析失败时,把错误传给错误处理中间件
        next(err);
      }
    });
  } else {
    // 非JSON请求直接跳过
    next();
  }
});

// 你的POST路由
router.post('/post', (req, res) => {
  console.log('解析后的请求体:', req.body);
  res.send('POST 请求已接收');
});

2. 捕获默认解析错误后重新尝试解析

如果不想引入第三方库,也可以先保留express.json(),但需要先读取原始body,解析失败后再用宽松方式重试:

const express = require('express');
const JSON5 = require('json5');
const router = express.Router();

// 先把JSON请求读取为原始buffer
router.use(express.raw({ type: 'application/json' }));

// 尝试用宽松格式解析
router.use((req, res, next) => {
  try {
    req.body = JSON5.parse(req.body.toString());
    next();
  } catch (err) {
    next(err);
  }
});

二、路由级错误中间件不生效的原因及修复

你的路由级错误中间件没触发,主要有两个关键原因:

1. 错误中间件的挂载顺序错误

Express的中间件是按挂载顺序依次执行的,错误处理中间件(带4个参数的(err, req, res, next))必须放在所有业务路由和普通中间件之后,这样前面抛出的错误才能被它捕获。你之前把错误中间件放在了路由最前面,自然抓不到后面路由抛出的错误。

2. 解析错误发生在路由栈之外

如果你的express.json()是挂载在app级(比如app.use(express.json())),那么JSON解析错误会在请求进入路由栈之前就发生,这时候路由级的错误中间件根本没机会处理,只能用app级的错误中间件捕获。

修复后的路由代码示例

把解析中间件、业务路由、错误处理中间件按正确顺序挂载,并且把解析逻辑放在路由内部,确保错误发生在路由栈内:

const express = require('express');
const JSON5 = require('json5');
const router = express.Router();

// 1. 先挂载解析中间件
router.use(express.raw({ type: 'application/json' }));
router.use((req, res, next) => {
  try {
    req.body = JSON5.parse(req.body.toString());
    next();
  } catch (err) {
    next(err); // 把错误传给后续的错误处理中间件
  }
});

// 2. 挂载业务路由
router.post('/post', (req, res) => {
  console.log(req.body);
  res.send('POST');
});

// 3. 最后挂载路由级错误处理中间件
router.use((error, req, res, next) => {
  console.log("Error handling middleware called...");
  if(error instanceof SyntaxError) {
    switch(error.type) {
      case 'entity.parse.failed':
        console.log('JSON格式不正确');
        break;
      default:
        console.log('其他语法错误');
        break;
    }
    res.status(400).send('请求JSON格式错误');
  } else {
    next(error); // 非解析错误,继续传给上层错误中间件
  }
});

module.exports = router;

这样调整后,路由级的错误中间件就能正常捕获解析过程中的错误了。

备注:内容来源于stack exchange,提问作者Morgan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 14:52:30