Avro запись с любым типом поля в Scala
Скажем, у меня есть простая пара ключ-значение в Avro, где значение может быть float
, double
, int
, string
так далее;
{"namespace": "com.namespace.kafka.event",
"type": "record",
"name": "RecordName",
"fields": [
{"name": "key", "type": "String"},
{"name": "value", "type": "Any/Object/Bytes???"}
]
}
Каков наилучший способ представить это в Avro?
- Иметь массив байтов, который каким-то образом десериализован в Scala, и вывести тип или добавить другое поле значения с метаданными.
- Создайте пользовательский тип записи для каждого примитивного типа, который имеет значение, и используйте общий анализ записей в Avro.
- Создайте пару ключ / значение для каждого типа примитива, который мы хотим представить.
Другая проблема в том, как бы мы представили это в Scala. Любой тип - это боль, гораздо приятнее знать тип, если он числовой и т. Д., Чем везде делать тесты типов...
2 ответа
Если вы используете avro4s, то вы можете использовать Either[A,B]
если у вас есть только два типа. Определите ваш класс дел для включения одного из них, например:
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()
Если у вас есть более двух типов, вы можете использовать Coproduct от Shapeless. Класс case теперь выглядит так:
case class Moo(coproduct: String :+: BigDecimal :+: CNil)
Если вы не знакомы с синтаксисом сопроизведения из бесформенного, то это немного необычно, когда вы впервые видите его, но вы просто комбинируете типы вместе, используя стиль инфикс, а +: + на самом деле является именем типа, подобного::
это имя непустого списка в стандартном скала.
Теперь вы создаете такие экземпляры:
val moo1 = Moo(Coproduct[String]("moo1"))
val moo2 = Moo(Coproduct[BigDecimal](12.3))
А в остальном тоже самое.
Смотрите модульные тесты в avro4s здесь для дальнейших примеров.
Вы можете попробовать использовать Union DataTypes of Avro?