如何使用 GenericRecordBuilder 设置记录数组

How to set array of records Using GenericRecordBuilder

我正在尝试将 Scala 对象(即 case class)转换为字节数组。

为此,我使用其特定模式将对象内容插入到 GenericRecordBuilder 中,并最终使用 GenericDatumWriter 将其转换为字节数组。

我可以在 GenericRecordBuilder 中设置基本类型和基本类型数组。

但是,我需要有关将记录数组插入 GenericRecordBuilder 并从中创建字节数组的帮助。

将记录数组插入 GenericRecordBuilder 的正确方法是什么?

这是我正在尝试做的部分工作:

这是架构:

{
    "type": "record",
    "name": "test1",
    "namespace": "ns",
    "fields": [
      {
        "name": "t_name",
        "type": "string",
        "default": "a"
      },
      {
        "name": "t_num",
        "type": "int",
        "default": 0
      },
      {"name" : "t_arr", "type":
        ["null",
         {"type": "array", "items": {
              "name": "t_arr_a",
              "type": "record",
              "fields": [
                {
                  "name": "t_arr_f1",
                  "type": "int",
                  "default": 0
                },
                {
                  "name": "t_arr_f2",
                  "type": "int",
                  "default": 0
                }
              ]
            }
            }
         ]
       }
    ]
}

这是填充 GenericRecordBuilder 并将其转换为字节数组的 Scala class:

package utils

import java.io.ByteArrayOutputStream

import org.apache.avro.{Schema, generic}
import org.apache.avro.generic.{GenericData, GenericDatumWriter}
import org.apache.avro.io.EncoderFactory
import org.apache.avro.generic.GenericRecordBuilder

object CheckRecBuilder extends App {

  val avroSchema: Schema = new Schema.Parser().parse(this.getClass.getResourceAsStream("/data/myschema.avsc"))
  val recordBuilder = new GenericRecordBuilder(avroSchema)

  recordBuilder.set("t_name", "X")
  recordBuilder.set("t_num", 100)


  recordBuilder.set("t_arr", ???)

  val record = recordBuilder.build()


  val w = new GenericDatumWriter[GenericData.Record](avroSchema)
  val outputStream = new ByteArrayOutputStream()
  val e = EncoderFactory.get.binaryEncoder(outputStream, null)
  w.write(record, e)
  val barr =  outputStream.toByteArray

  println("End")

}

我设法设置了对象数组。

我想知道是否有更好或更正确的方法。

这是我所做的:

  1. 创建案例class:

case class t_arr_a(t_arr_f1:Int, t_arr_f2:Int)

  1. 创建了一种将大小写 class 转换为 GenericData.Record:
  2. 的方法

def caseClassToGenericDataRecord(cc:Product, schema:Schema): GenericData.Record = { val childRecord = new GenericData.Record(schema.getElementType)<br> val 值 = cc.productIterator cc.getClass.getDeclaredFields.map(f => childRecord.put(f.getName, values.next )) 子记录 }

  1. 更新了上面的 class CheckRecBuilder:

替换为:

recordBuilder.set("t_arr", ???)

有:

  val childSchema = new GenericData.Record(avroSchema2).getSchema.getField("t_arr").schema().getTypes().get(1)
  val tArray = Array(t_arr_a(2,4), t_arr_a(25,14))
  val tArrayGRecords: util.List[GenericData.Record] 
    = Some(yy.map(x => caseClassToGenericDataRecord(x,childSchema))).map(arr => java.util.Arrays.asList(arr: _*)).orNull

  recordBuilder.set("t_arr", tArrayGRecords)