web-dev-qa-db-fra.com

Avro avec Java 8 dates comme type logique

Le dernier compilateur Avro (1.8.2) génère Java sources pour types logiques de dates avec Joda-Time implémentations basées. Comment puis-je configurer Avro compilateur pour produire des sources utilisant Java 8 API date-heure?

16
injecto

Actuellement (avro 1.8.2) ce n'est pas possible. Il est codé en dur pour générer des classes de date/heure Joda.

La branche master actuelle est passée à Java 8 et il y a problème ouvert (avec Pull Request ) à ajouter la possibilité de générer des classes avec Java.time.* les types.

Je n'ai aucune idée de tout type de calendrier de sortie pour ce qui est actuellement dans master malheureusement. Si vous vous sentez aventureux, vous pouvez appliquer le patch à 1.8.2, car en théorie, tout devrait être compatible. Les types de base sous-jacents lors de la sérialisation/désérialisation sont toujours des nombres entiers et longs.

13
Auke

Vous devez créer votre propre Conversion s pour prendre en charge l'API date-heure Java-8, voici une conversion pour 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);
    }
}

Les types logiques peuvent être réutilisés dans avro, vous pouvez donc utiliser le type logique date existant, par exemple:

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

Pour la sérialisation et la désérialisation, vous devez définir le GenericData qui trouvera votre propre conversion, par exemple:

//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;
}

Si vous ne souhaitez pas configurer le GenericData à chaque fois, vous pouvez utiliser le global GenericData à la place, par exemple:

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

Avec avro 1.9.2, vous pouvez utiliser par exemple date pour LocalDate:

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

Voir Types logiques pour les autres types.

0
adrhc