1

我正在尝试制作一个通用函数,它CodecProvider从给定的通用案例类中生成一个。

BSON 宏文档没有给出任何例子。

这个(未回答的)SO问题是相似的,但是我对枚举给定类型参数的所有可能的编解码器不感兴趣。此外,我的问题不涉及类型界限或类型差异。

这是无法编译的代码的最小示例。

import org.mongodb.scala.bson.codecs.Macros

case class Foo(x: Int)

case class Bar[T](x: T)

def fooCodecProvider = Macros.createCodecProvider[Foo]()
// Compiles! (No generic)

def barCodecProvider[T] = Macros.createCodecProvider[Bar[T]]()
// Compile Error:(8, 70) class Bar takes type parameters

我希望barCodecProvider编译,但它没有。

上面代码抛出的编译错误读起来class Bar takes type parameters令人困惑,因为我已经通过泛型函数的签名明确提供了T类型Bar参数barCodecProvider。我有与打字相关的语法错误吗?错误是否表明我错误地使用了 mongo-scala-driver?

4

1 回答 1

2

虽然它可以通过隐式查找与其他库(如 circe)一起使用。这似乎是不可能的,org.mongodb.scala.bson.codecs.Macros因为没有Macro函数接受参数。

但是,如果您知道如何制作Codec.

编解码器似乎是一个简单的特征,有 3 种方法encode decodegetEncoderClass

implicit val fooCodec : Codec[Foo] = Macros.createCodecProvider[Foo]()

def barCodecProvider[T: ClassTag](implicit codecT : Codec[T]) = new Codec[Bar[T]] {
  override def decode(reader: BsonReader, decoderContext: DecoderContext): Bar[T] = {
    Bar[T](codecT.decode(reader,decoderContext))
  }

  override def encode(writer: BsonWriter, value: Bar[T], encoderContext: EncoderContext): Unit = {
    codecT.encode(writer,  value.x, encoderContext)
  }
  //the tricky one
  override def getEncoderClass: Class[Bar[T]] = classTag[Bar[T]].runtimeClass.asInstanceOf[Class[Bar[T]]]
}

val barFooCodec : Codec[Bar[Foo]] = barCodecProvider[Foo]

这是一个简单的例子,但它给出了你可以做什么的想法。使用宏生成简单实例,并使用隐式函数将这些实例与函数组合在一起,以自动获取正确的实例。

于 2019-07-05T08:34:23.637 回答