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

测试Express接口时反复出现Unexpected end of JSON input错误导致程序崩溃的问题排查

解决Express + Mongoose中GET /messages/sync接口的"Unexpected end of JSON input"崩溃问题

我来帮你排查这个问题,这个错误通常和响应未正确完成或者JSON序列化失败有关,再加上缺少全局错误处理,导致程序直接崩溃。咱们一步步来修复:

1. 替换Mongoose回调为Async/Await(更可靠的错误处理)

你现在用的是Mongoose的回调模式,这种模式下如果出现未捕获的错误,很容易导致程序崩溃。换成async/await可以更清晰地捕获错误,同时避免回调嵌套的问题:

app.get('/messages/sync', async (req, res) => {
  try {
    const data = await Messages.find({}); // 空对象表示查询所有文档
    res.status(200).json(data); // 用res.json()代替res.send(),确保正确序列化JSON
  } catch (err) {
    console.error('获取消息失败:', err);
    res.status(500).json({ error: '获取消息失败', details: err.message });
  }
});

// 同样把POST接口也改成async/await模式,保持代码风格一致
app.post('/messages/new', async (req, res) => {
  try {
    const dbMessage = req.body;
    const data = await Messages.create(dbMessage);
    res.status(201).json(data);
  } catch (err) {
    console.error('创建消息失败:', err);
    res.status(500).json({ error: '创建消息失败', details: err.message });
  }
});

用res.json()代替res.send()的核心原因是:它会自动设置Content-Type: application/json响应头,并且内部会处理JSON序列化的细节,避免手动发送时可能出现的序列化失败问题。

2. 添加全局错误处理中间件

Express如果遇到未被捕获的错误,默认会直接崩溃程序。添加一个全局错误处理中间件,可以捕获所有路由里的漏网错误,让程序保持运行:

// 注意:这个中间件要放在所有路由定义的后面
app.use((err, req, res, next) => {
  console.error('全局错误捕获:', err.stack);
  res.status(500).json({ error: '服务器内部错误', message: err.message });
});

这个中间件会接住任何路由里没被try/catch捕获的错误,把错误信息格式化后返回给客户端,同时避免程序直接崩溃。

3. 检查Mongoose模型是否有不可序列化的字段

如果你的Messages模型里包含特殊类型(比如Buffer、Map或者自定义类型),JSON序列化时可能会失败。检查你的dbMessages.js模型,确保所有字段都是可JSON序列化的:

比如如果有Buffer类型的字段,可以在模型里设置toJSON转换规则:

const messageSchema = new mongoose.Schema({
  // 你的字段定义
  attachment: { type: Buffer }
}, {
  toJSON: {
    transform: function(doc, ret) {
      // 把Buffer转成base64字符串,或者直接删除如果不需要返回给客户端
      ret.attachment = ret.attachment ? ret.attachment.toString('base64') : null;
    }
  }
});

4. 给数据库连接添加错误处理

当前的mongoose.connect没有错误处理逻辑,如果数据库连接失败,后续的数据库操作会抛出未捕获的错误,直接导致程序崩溃。给连接加上错误处理:

mongoose.connect(connection_url, { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => console.log('数据库连接成功'))
  .catch(err => console.error('数据库连接失败:', err));

为什么之前的代码会崩溃?

之前的回调模式中,如果Messages.find()抛出错误(比如数据库连接断开),err对象本身可能包含循环引用(Mongoose的错误对象经常有这类结构),导致res.send(err)无法完成JSON序列化,进而触发"Unexpected end of JSON input"错误;同时因为没有全局错误处理,程序会直接崩溃。

按照上面的步骤修改后,应该就能解决这个问题,同时代码的可维护性和稳定性也会大幅提升。

内容的提问来源于stack exchange,提问作者Mel_moa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 01:02:33