如何将嵌套的avro GenericRecord转换为Row

时间:2018-02-16 13:40:11

标签: java apache-spark avro spark-avro

我有一个代码可以使用函数for (i = 0; i <= ds.Tables[0].Columns.Count - 1; i++) { data = ds.Tables[0].Columns[i].ColumnName.ToString(); xlWorkSheet.Cells[1, i + 1] = data; }

将我的avro记录转换为Row
avroToRowConverter()

此函数不适用于嵌套模式directKafkaStream.foreachRDD(rdd -> { JavaRDD<Row> newRDD= rdd.map(x->{ Injection<GenericRecord, byte[]> recordInjection = GenericAvroCodecs.toBinary(SchemaRegstryClient.getLatestSchema("poc2")); return avroToRowConverter(recordInjection.invert(x._2).get()); });

(TYPE= UNION)

有人建议我如何将复杂架构转换为ROW?

1 个答案:

答案 0 :(得分:6)

SchemaConverters.createConverterToSQL,但不幸的是它是私密的。 有PR公开,但它们从未合并过:

虽然我们使用过,但还有一个解决方法。

您可以通过在com.databricks.spark.avro包中创建一个类来公开它:

package com.databricks.spark.avro

import org.apache.avro.Schema
import org.apache.avro.generic.GenericRecord
import org.apache.spark.sql.Row
import org.apache.spark.sql.types.DataType

object MySchemaConversions {
  def createConverterToSQL(avroSchema: Schema, sparkSchema: DataType): (GenericRecord) => Row =
    SchemaConverters.createConverterToSQL(avroSchema, sparkSchema).asInstanceOf[(GenericRecord) => Row]
}

然后你可以在你的代码中使用它:

final DataType myAvroType = SchemaConverters.toSqlType(MyAvroRecord.getClassSchema()).dataType();

final Function1<GenericRecord, Row> myAvroRecordConverter =
        MySchemaConversions.createConverterToSQL(MyAvroRecord.getClassSchema(), myAvroType);

Row[] convertAvroRecordsToRows(List<GenericRecord> records) {
    return records.stream().map(myAvroRecordConverter::apply).toArray(Row[]::new);
}

对于一条记录,您可以这样称呼它:

final Row row = myAvroRecordConverter.apply(record);