【问题标题】:Accessing nested fields in AVRO GenericRecord (Java/Scala)访问 AVRO GenericRecord (Java/Scala) 中的嵌套字段
【发布时间】:2016-03-01 17:19:09
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我知道我可以通过执行以下操作访问嵌套类型的架构:parsedSchema.getField("toplevel").schema 然后我可以使用它来解码 GenericRecord 返回的嵌套对象吗?

标签: java scala avro


【解决方案1】:

我想出了一种方法。将返回的Object 转换为GenericRecord

示例(scala):

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

然后我可以通过执行以下操作访问该新 GenericRecord 中的嵌套字段:

data_nestedObj.get("nestedField")

这对我来说已经足够好了。

【讨论】:

  • 对于嵌套数组,你必须转换为GenericData.Array[GenericRecord]
  • 这对我不起作用。它说它不能将 utf8 转换为 GenericRecord
  • @deadpool 这意味着你的值是一个字符串而不是一个对象,所以它不能转换为GenericRecord
【解决方案2】:

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

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

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

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

val format = RecordFormat[Foo]

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

val record = format.to(someFoo)

val foo = format.from(someRecord)

【讨论】:

  • 我宁愿避免将另一个库用于(看似)如此简单的事情。感谢您发布链接和解释!
  • 如果你想让 deps 保持低调,那当然可以,但是在这方面使用 Avro 有点烦人(很多样板文件要编写从 GenericRecords 转换等 :(
  • 我完全同意...如果他们添加了类似(或部分)您正在处理的内容,那就太好了。
【解决方案3】:

@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
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-27
    • 2015-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多