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

时间:2016-03-01 17:19:09

标签: java scala avro

我有一个嵌套字段的GenericRecord。当我使用$.ajax({ type: "POST", global: false, contentType : 'application/json; charset=utf-8', //dataType: "text", //dataType : 'json', url: '${urlAddr}', data: JSON.stringify(fieldArray), success :function(result) { console.log("yupii... Success"); }, error: function(objRequest ){ console.log("error"); console.log(objRequest.responseText); } }); 时,它返回一个包含嵌套AVRO数据的Object。

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

有一个简单的方法吗?

当我执行genericRecord.get(1).get(0)之类的操作时,它会显示returnedObject.get("item")

3 个答案:

答案 0 :(得分:4)

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

示例(scala):

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

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

data_nestedObj.get("nestedField")

这对我来说效果很好。

答案 1 :(得分:3)

您可以使用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)

答案 2 :(得分:0)

@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) =>
          (tuple._1, Option(value))
        case _ =>
          (tuple._1, None)
      }
    }._2
  }