来自泛型的 Avro 序列化

Avro Serialization from generics

这是一个基于 Avro4s 的 GitHub 页面的非常简单的示例,工作正常

object Main extends App {

  case class Ingredient(name: String, sugar: Double, fat: Double)
  case class Pizza(name: String, ingredients: Seq[Ingredient], vegetarian: Boolean, vegan: Boolean, calories: Int)

  val pepperoni = Pizza("pepperoni", Seq(Ingredient("pepperoni", 12, 4.4), Ingredient("onions", 1, 0.4)), false, false, 98)
  val hawaiian = Pizza("hawaiian", Seq(Ingredient("ham", 1.5, 5.6), Ingredient("pineapple", 5.2, 0.2)), false, false, 91)

  val format = RecordFormat[Pizza]
  val recordInAvro = format.to(pepperoni)
  printf(s"Avro of Pepperoni: $recordInAvro\n")
}

但是我想做的是这样的:

object Main extends App {

  case class Ingredient(name: String, sugar: Double, fat: Double)
  case class Pizza(name: String, ingredients: Seq[Ingredient], vegetarian: Boolean, vegan: Boolean, calories: Int)

  val pepperoni = Pizza("pepperoni", Seq(Ingredient("pepperoni", 12, 4.4), Ingredient("onions", 1, 0.4)), false, false, 98)
  val hawaiian = Pizza("hawaiian", Seq(Ingredient("ham", 1.5, 5.6), Ingredient("pineapple", 5.2, 0.2)), false, false, 91)

  def toAvro[T](obj: T): GenericRecord = RecordFormat[T].to(obj)

  val recordInAvro = toAvro[Pizza](pepperoni)
  printf(s"Avro of Pepperoni: $recordInAvro\n")
}

然而,尽管最后一段代码看起来不错,但在编译期间出现以下错误:

Error:(14, 54) could not find implicit value for parameter toRecord: com.sksamuel.avro4s.ToRecord[T]
  def toAvro[T](obj: T): GenericRecord = RecordFormat[T].to(obj)
Error:(14, 54) not enough arguments for method apply: (implicit toRecord: com.sksamuel.avro4s.ToRecord[T], implicit fromRecord: com.sksamuel.avro4s.FromRecord[T])com.sksamuel.avro4s.RecordFormat[T] in object RecordFormat.
Unspecified value parameters toRecord, fromRecord.
  def toAvro[T](obj: T): GenericRecord = RecordFormat[T].to(obj)

关于如何使 Avro 序列化与泛型一起工作的任何提示?谢谢。

尝试将您的定义更改为

def toAvro[T: ToRecord: FromRecord](obj: T): GenericRecord = RecordFormat[T].to(obj)

更多信息here and here

简而言之:当您使用具体类型时,编译器可以自动找到所需的 ToRecord 隐式值。但是在参数化代码中,你应该向编译器保证你会以某种方式向它提供这个隐式值。