访问 AVRO GenericRecord 中的嵌套字段 (Java/Scala)

Accessing nested fields in AVRO GenericRecord (Java/Scala)

我有一个带有嵌套字段的 GenericRecord。当我使用 genericRecord.get(1) 时,它 returns 一个包含嵌套 AVRO 数据的对象。

我希望能够像 genericRecord.get(1).get(0) 那样访问该对象,但我不能,因为 AVRO returns 一个对象。

有解决这个问题的简单方法吗?

当我执行类似 returnedObject.get("item") 的操作时,它会显示 item not a member of returnedObject

我想出了一个办法。将返回的 Object 转换为 GenericRecord.

示例(scala):

val data_nestedObj = (data.get("nestedObj")).asInstanceOf[GenericRecord]

然后我可以通过以下方式访问新 GenericRecord 中的嵌套字段:

data_nestedObj.get("nestedField")

这对我来说效果很好。

您可以使用 avro 序列化库来帮助您。例如https://github.com/sksamuel/avro4s(我是作者)但还有其他人

您只需为要获取的数据类型定义一个案例 class,这可以包括嵌套案例 classes。例如,

case class Boo(d: Boolean)
case class Foo(a: String, b: Int, c: Boo)

然后创建 RecordFormat 类型的实例class。

val format = RecordFormat[Foo]

最后,您可以使用它来提取记录或创建记录。

val record = format.to(someFoo)

val foo = format.from(someRecord)

@rye 的回答是正确的并且工作正常,但如果你可以避免使用 asInstanceOf 那么你应该。所以我写了下面的方法来检索嵌套字段。

  /**
    * Get the value of the provided property. If the property contains `.` it assumes the property is nested and
    * parses the avroRecord with respective number of nested levels and retrieves the value at that level.
    */
  def getNestedProperty(property: String, avroRecord: GenericRecord): Option[Object] = {
    val tokens = property.split("\.")

    tokens.foldLeft[Tuple2[GenericRecord, Option[Object]]]((avroRecord,None)){(tuple, token) =>
      tuple._1.get(token) match {
        case value: GenericRecord =>
          (value, tuple._2)
        case value @ (_:CharSequence | _:Number | _: ByteBuffer) =>
          (tuple._1, Option(value))
        case _ =>
          (tuple._1, None)
      }
    }._2
  }