2

假设我在 Avro 中有一个简单的键值对,其中的值可以是 a floatdoubleintstring

{"namespace": "com.namespace.kafka.event",
 "type": "record",
 "name": "RecordName",
 "fields": [
    {"name": "key", "type": "String"},
    {"name": "value", "type": "Any/Object/Bytes???"}
 ]
}

在 Avro 中表示这一点的最佳方式是什么?

  1. 有一个字节数组,在 Scala 中以某种方式反序列化并推断类型或添加另一个带有元数据的值字段
  2. 为每个有值的原始类型创建一个自定义记录类型,并使用 Avro 中的通用记录解析
  3. 为我们希望表示的每个原始值类型创建一个键/值对。

另一个问题是我们如何在 Scala 中表示它。拥有 Any 类型是一件痛苦的事情,知道类型(如果它的数字等)要好得多,而不必到处进行类型测试......

4

2 回答 2

2

如果您使用的是avro4sEither[A,B] ,那么如果您只有两种类型,则可以使用 an 。定义您的案例类以包括其中之一,例如:

case class Moo(either: Either[String, BigDecimal])

然后你可以为它创建一个模式:

val schema = Schemafor[Moo]

或者写出数据:

val moo1 = Moo(Left("moo1"))
val moo2 = Moo(Right(12.3))

val output = new ByteArrayOutputStream
val avro = AvroOutputStream.data[Moo](output)
avro.write(moo1, moo2)
avro.close()

并读入数据:

val in = AvroInputStream.data[Moo](bytes)
val moos = in.iterator.toList
in.close()

如果您有两种以上的类型,则可以使用 Shapeless 的Coproduct。案例类现在看起来像这样:

case class Moo(coproduct: String :+: BigDecimal :+: CNil)

如果您不熟悉 shapeless 的 coproduct 语法,那么当您第一次看到它时会有点不寻常,但是您只是使用中缀样式将类型组合在一起,而 +:+ 实际上是类型的名称,::例如标准scala中非空列表的名称。

现在你创建这样的实例:

val moo1 = Moo(Coproduct[String]("moo1"))
val moo2 = Moo(Coproduct[BigDecimal](12.3))

其余的都是一样的。

有关更多示例,请参见此处的 avro4s 中的单元测试。

于 2016-09-12T22:12:29.910 回答
1

您可以尝试使用 Avro 的 Union DataTypes 吗?

https://avro.apache.org/docs/1.8.1/spec.html#Unions

于 2016-09-12T04:06:06.497 回答