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

Next.js与MongoDB数据序列化问题:为何需重复执行JSON.parse?

为什么Next.js的getServerSideProps返回MongoDB数据会触发SerializableError?

核心原因是MongoDB查询返回的不是普通JavaScript对象,而是BSON文档实例,这类对象包含Next.js序列化机制无法处理的特殊内容:

  • 自带MongoDB专属类型:比如ObjectId、Decimal128、Binary等,这些类型不在JSON标准的序列化范围内;
  • 存在不可枚举属性或循环引用:BSON对象内部有引擎相关的隐藏属性,部分结构还存在循环引用,导致JSON序列化失败;
  • 部分类型的原生序列化行为不符合要求:比如部分BSON衍生的日期类型,其序列化逻辑和普通Date对象有差异,无法被Next.js正常处理。

你用JSON.stringify能解决问题,是因为这个方法会强制把BSON对象转成纯JSON字符串——过程中自动忽略不可序列化的属性,把特殊类型(比如ObjectId)转成字符串,消除循环引用。但代价是客户端拿到的是字符串,必须JSON.parse才能转成可用对象,还会丢失原始类型信息(比如Date变成ISO字符串,需要手动转回Date对象)。

更优解决方案(不用来回序列化)

直接让MongoDB返回普通JS对象,避免BSON实例的问题:

  1. 使用lean()查询
    在MongoDB查询语句后加上.lean(),它会跳过BSON文档实例的创建,直接返回纯JS对象,Next.js可以直接序列化:

    async function getLatestEpisodeData() {
      const db = await getMongoDbConnection(); // 你的数据库连接方法
      // 加上.lean()返回普通JS对象
      const latestEpisode = await db.collection('episodes')
        .findOne({}, { sort: { createdAt: -1 } })
        .lean();
      return latestEpisode;
    }
    

    这样getServerSideProps直接返回该数据,组件拿到的就是可用对象,不需要再做JSON.parse。

  2. 手动转换特殊字段
    如果需要保留部分BSON类型的信息,可以手动处理:

    const episode = await db.collection('episodes').findOne(...);
    // 把ObjectId转成字符串
    episode._id = episode._id.toString();
    // 如果有Decimal128类型,转成字符串或数字
    episode.price = episode.price.toString();
    return episode;
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 00:20:37