Как установить массив записей, используя GenericRecordBuilder - PullRequest
1 голос
/ 27 мая 2019

Я пытаюсь превратить объект Scala (т.е. класс case) в байтовый массив.

Чтобы сделать это, я вставляю содержимое объекта в 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
                }
              ]
            }
            }
         ]
       }
    ]
}

Это класс Scala, который заполняет GenericRecordBuilder и преобразует его в байтовый массив:

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 Ответ

0 голосов
/ 27 мая 2019

Мне удалось установить массив объектов.

Интересно, есть ли лучший или правильный способ сделать это?

Вот что я сделал:

  1. Создан класс дела:

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

Создан метод, который преобразует класс case в GenericData.Record:

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

Обновлен класс 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...