【发布时间】:2021-03-02 07:35:39
【问题描述】:
我正在尝试根据类路径在反射中生成 Avro4s 的 RecordFormat。以下代码会引发错误。
case class MyCaseClass(a: Int)
println(toolBox.compile {
toolBox.parse(
s"""
|import com.sksamuel.avro4s._
|import mypackage.MyCaseClass
|RecordFormat[MyCaseClass]
|""".stripMargin
)
}())
找不到 com.sksamuel.avro4s.Decoder[mypackage.MyCaseClass] 类型的证据参数的隐式值
RecordFormat 就像
object RecordFormat {
def apply[T <: Product : Encoder : Decoder : SchemaFor]: RecordFormat[T] = apply(AvroSchema[T])
def apply[T <: Product : Encoder : Decoder](schema: Schema): RecordFormat[T] = new RecordFormat[T] {
private val fromRecord = FromRecord[T](schema)
private val toRecord = ToRecord[T](schema)
override def from(record: GenericRecord): T = fromRecord.from(record)
override def to(t: T): Record = toRecord.to(t)
}
}
我可以看到,它可以解析 Encoder[MyCaseClass] 和 SchemaFor[MyCaseClass] 但对于 Decoder[MyCaseClass] 失败。
同样的代码无需反射就可以解析RecordFormat[MyCaseClass]。
我可以看到Decoder 是用类似于Encoder 的宏实现的。
implicit def applyMacro[T <: Product]: Decoder[T] = macro applyMacroImpl[T]
为什么反思不能解决隐含的证据?
【问题讨论】:
-
运行时反射很少是合适的解决方案
-
我的类路径中有 +1000 案例类定义在不同的包中,并且不是由我维护的。我的逻辑基本上接受类的完整路径进行数据处理。我正在尝试使用 avro 而不是 json,并且需要从 avro4s 创建
RecordFormat。您是否推荐更合适的解决方案,因为 RecordFormat 高度依赖于宏。 -
@lalala 无法复制。
Decoder似乎和SchemaFor和Encoderscastie.scala-lang.org/HZR8Kf1WQkGtqOsc5efWuQ 我在 Scastie 制作了mypackage一个对象,但如果它是一个包,本地行为对我来说是相同的。斯卡拉 2.13.3,avro4s 4.0.1。对象RecordFormat内线右侧的apply是什么?现在似乎是从左侧递归调用apply,这不可能是正确的。 -
@DmytroMitin 我的 Avro4s 版本是 2.x 和 Scala 2.11,不知道是不是这个原因。
-
@DmytroMitin,关于递归调用,我已经用完整的库实现和参考链接更新了这个问题
标签: scala reflection scala-macros scala-reflect avro4s