avro4s不能反序列化AnyRef

时间:2018-08-01 15:03:56

标签: scala apache-kafka avro4s akka-kafka

我有一个简单的案例类

case class KafkaContainer(key: String, payload: AnyRef)

然后我想通过生产者将其发送给kafka主题

val byteArrayStream = new ByteArrayOutputStream()
      val output = AvroOutputStream.binary[KafkaContainer](byteArrayStream)
      output.write(msg)
      output.close()
      val bytes = byteArrayStream.toByteArray
      producer.send(new ProducerRecord("my_topic", msg.key, bytes))

这很好用

然后我尝试食用

Consumer.committableSource(consumerSettings, Subscriptions.topics("my_topic"))
    .map { msg =>
      val in: ByteArrayInputStream = new ByteArrayInputStream(msg.record.value())
      val input: AvroBinaryInputStream[KafkaContainer] = AvroInputStream.binary[KafkaContainer](in)
      val result: Option[KafkaContainer] = input.iterator.toSeq.headOption
      input.close()
        ...
    }.runWith(Sink.ignore)

,这对于有效负载中的任何类都可以很好地工作。

但是!如果有的话。消费者代码失败并

  

错误:(38,96)找不到证据参数的隐式值   类型   com.sksamuel.avro4s.FromRecord [test.messages.KafkaContainer]         val输入:AvroBinaryInputStream [KafkaContainer] = AvroInputStream.binaryKafkaContainer

     

错误:(38,96)不够   方法二进制的参数:(隐式证据$ 21:   com.sksamuel.avro4s.SchemaFor [test.messages.KafkaContainer],   隐性证据$ 22:   com.sksamuel.avro4s.FromRecord [test.messages.KafkaContainer])com.sksamuel.avro4s.AvroBinaryInputStream [test.messages.KafkaContainer]。   未指定的价值参数证据$ 22。         val输入:AvroBinaryInputStream [KafkaContainer] = AvroInputStream.binaryKafkaContainer

如果我用...声明隐式

implicit val schemaFor: SchemaFor[KafkaContainer] = SchemaFor[KafkaContainer]
implicit val fromRecord: FromRecord[KafkaContainer] = FromRecord[KafkaContainer]

无法编译

  

错误:(58,71)找不到类型的惰性隐式值   com.sksamuel.avro4s.FromValue [Object]         隐式val fromRecord:FromRecord [KafkaContainer] = FromRecord [KafkaContainer]

     

错误:(58,71)没有足够的参数用于   方法lazyConverter:(隐式fromValue:   shapeless.Lazy [com.sksamuel.avro4s.FromValue [Object]])shapeless.Lazy [com.sksamuel.avro4s.FromValue [Object]]。   未指定的值参数fromValue。         隐式val fromRecord:FromRecord [KafkaContainer] = FromRecord [KafkaContainer]

如果添加每个需要编译器的隐式

lazy implicit val fromValue: FromValue[Object] = FromValue[Object]
implicit val fromRecordObject: FromRecord[Object] = FromRecord[Object]
implicit val schemaFor: SchemaFor[KafkaContainer] = SchemaFor[KafkaContainer]
implicit val fromRecord: FromRecord[KafkaContainer] = FromRecord[KafkaContainer]

编译失败,并显示错误

  

错误:(58,69)宏扩展期间发生异常:   java.lang.IllegalArgumentException:要求失败:需要案例   类但对象不在scala.Predef $ .require(Predef.scala:277)     在com.sksamuel.avro4s.FromRecord $ .applyImpl(FromRecord.scala:283)         隐式val fromRecordObject:FromRecord [Object] = FromRecord [Object]

但是如果我将AnyRef替换为某个类-不需要隐式,一切都会再次正常运行

1 个答案:

答案 0 :(得分:0)

我使用Any数据类型遇到类似的问题。您必须指定此成员变量的有效类型,因为Any或AnyRef可以是任何东西。然后,使用“无形”或“无形”(另请参见Github Documentation)。 就我而言,它可以是String,Long,Double或null,因此使用shapeless可以做到:

case class DataContainer(name: String, value: Option[String:+:Long:+:Double:+:CNil])

这将在AVRO中转换为联合类型:

{
    "name" : "value",
    "type" : [ "null", "string", "long", "double" ]
}