簡體   English   中英

Avro 將 Java 8 日期作為邏輯類型

[英]Avro with Java 8 dates as logical type

最新的 Avro 編譯器 (1.8.2) 使用基於Joda-Time的實現為日期邏輯類型生成 Java 源代碼。 如何配置 Avro 編譯器以生成使用 Java 8 日期時間 API 的源代碼?

目前(avro 1.8.2)這是不可能的。 生成 Joda 日期/時間類是硬編碼的。

當前的master分支已切換到 Java 8,並且有一個未解決的問題(使用Pull Request )以添加生成具有java.time.*類型的類的能力。

不幸的是,我不知道當前master任何內容的發布時間表。 如果你喜歡冒險,你可以將補丁應用到1.8.2 ,因為理論上它應該都是兼容的。 序列化/反序列化時的底層基本類型仍然是整數和長整數。

您需要創建自己的Conversion來支持 java-8 date-time api,下面是java.time.LocalDate的轉換:

class Java8LocalDateConversion extends Conversion<LocalDate> {
    @Override
    public Class<LocalDate> getConvertedType() {
        return LocalDate.class;
    }

    @Override
    public String getLogicalTypeName() {
        //      v--- reuse the logical type `date`
        return "date";
    }

    @Override
    // convert LocalDate to Integer
    public Integer toInt(LocalDate value, Schema schema, LogicalType type) {
        return (int) value.toEpochDay();
    }

    @Override
    // parse LocalDate from Integer
    public LocalDate fromInt(Integer value, Schema schema, LogicalType type) {
        return LocalDate.ofEpochDay(value);
    }
}

邏輯類型可以在 avro 中重用,因此您可以使用現有的date邏輯類型,例如:

Schema schema = LogicalTypes.date().addToSchema(Schema.create(Type.INT));

對於序列化和反序列化,您應該設置GenericData它將找到您自己的轉換,例如:

//serializing
DatumWriter<T> out = new SpecificDatumWriter<>(schema, data());

// deserializing
DatumReader<T> in = new SpecificDatumReader<>(schema, schema, data());

private SpecificData data() {
    SpecificData it = new SpecificData();
    it.addLogicalTypeConversion(new Java8LocalDateConversion());
    return it;
}

如果不想每次都配置GenericData ,可以改用全局GenericData ,例如:

//      register the conversion globally ---v
SpecificData.get().addLogicalTypeConversion(new Java8LocalDateConversion());

使用 avro 1.9.2 您可以使用例如日期LocalDate

    {
      "name": "Transaction",
      "type": "record",
      "fields": [
        {
          "name": "time",
          "type": {
            "type": "int",
            "logicalType": "date"
          }
        },

有關其他類型,請參閱邏輯類型

  • 使用 Avro 版本 >= 1.9.0 < 1.10.0
  • <dateTimeLogicalTypeImplementation>jsr310</dateTimeLogicalTypeImplementation>configuration部分。
  • 使用 Avro 版本 >= 1.10.0
  • 默認使用的 java8/jsr310 原生日期/時間類

AVRO 1.10 添加了對LocalDateTime支持,請參閱Apache Avro™ 1.10.0 規范

Avro v1.11.0 TimeConversions內置支持 Java 8 時間類,例如LocalDateInstant等。 TimeConversions必須注冊到SpecificData類或其子類,例如ReflectData 以下是如何使用TimeConversions的完整示例:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account
{
    private int id;
    private LocalDate createdOn;

    public static void main(String[] args) throws IOException
    {
        // create schema from POJO Account class
        ReflectData reflectData = ReflectData.get();
        reflectData.addLogicalTypeConversion(new TimeConversions.DateConversion());
        Schema schema = reflectData.getSchema(Account.class);
        System.out.println("Schema in JSON:\n" + schema + "\n");

        // create avro writer
        DatumWriter<Account> datumWriter = new ReflectDatumWriter<>(schema);
        DataFileWriter<Account> dataFileWriter = new DataFileWriter<>(datumWriter);
        // dataFileWriter.setCodec(CodecFactory.snappyCodec()); // for compression
        dataFileWriter.create(schema, new File("accounts.avro"));
        dataFileWriter.append(new Account(123, LocalDate.of(2001, 1, 1)));
        dataFileWriter.append(new Account(234, LocalDate.of(2002, 2, 2)));
        dataFileWriter.close();

        // create avro reader
        DatumReader<Account> datumReader = new ReflectDatumReader<>(schema);
        DataFileReader<Account> dataFileReader = new DataFileReader<>(new File("accounts.avro"), datumReader);
        dataFileReader.forEach(System.out::println);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM