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

Scala 2.11.11下MongoDB驱动ADT编解码器编译失败求助

解决Scala 2.11下MongoDB驱动ADT Codec编译错误的问题

这个错误是Scala 2.11和2.12宏系统的行为差异导致的。Mongo Scala Driver的Macros.createCodecProvider宏在Scala 2.11环境下,要求sealed类的所有子类必须先被编译器完全处理,才能生成对应的Codec;而Scala 2.12对宏系统做了优化,自动兼容了父类在前、子类在后的定义顺序。

针对你的场景,有两种简单可行的解决方案:

方案一:延迟Codec初始化(推荐)

把Codec和CodecRegistry的定义改为lazy val,让编译器延迟到首次使用它们时再执行宏解析,这时所有子类已经被正确加载完成:

import org.mongodb.scala.bson.codecs.{DEFAULT_CODEC_REGISTRY, Macros}
import org.bson.codecs.configuration.CodecRegistries.{fromProviders, fromRegistries}

object Models {
  sealed class Tree
  case class Branch(b1: Tree, b2: Tree, value: Int) extends Tree
  case class Leaf(value: Int) extends Tree

  // 用lazy val延迟宏的执行时机
  lazy val treeCodec = Macros.createCodecProvider[Tree]()
  lazy val treeCodecRegistry = fromRegistries(
    fromProviders(treeCodec),
    DEFAULT_CODEC_REGISTRY
  )
}

方案二:将Codec定义放在嵌套对象中

把Codec相关代码放到一个嵌套的object里,利用Scala的编译顺序(先处理外部类的所有成员,再处理嵌套对象),确保子类在宏执行前已经完成定义:

import org.mongodb.scala.bson.codecs.{DEFAULT_CODEC_REGISTRY, Macros}
import org.bson.codecs.configuration.CodecRegistries.{fromProviders, fromRegistries}

object Models {
  sealed class Tree
  case class Branch(b1: Tree, b2: Tree, value: Int) extends Tree
  case class Leaf(value: Int) extends Tree

  // 嵌套对象会在外部类所有成员处理完成后编译
  object Codecs {
    val treeCodec = Macros.createCodecProvider[Tree]()
    val treeCodecRegistry = fromRegistries(
      fromProviders(treeCodec),
      DEFAULT_CODEC_REGISTRY
    )
  }
}

// 使用时通过 Models.Codecs.treeCodecRegistry 访问

为什么Scala 2.12下正常?

Scala 2.12改进了宏系统对sealed类的处理逻辑,能够自动识别同一编译单元内的子类,不需要额外调整初始化时机,所以你的原始代码在2.12环境下可以直接编译通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:54:39