在java上使用Avro发送和接收日期类型

问题描述 投票:0回答:1

有没有我可以发送和接收日期类型与Apache Avro。我一直没能找到任何东西。只有我发现的东西说在模式中使用了Date和logicalType of Date。但这导致接收器端的另一个int。我仍然需要将它转换为日期。

我试图从Apache Kafka制作人发送日期并在Kafka消费者中收到。

如果没有其他方法,那么我必须始终将日期转换为int,然后返回消费者。这篇文章介绍了如何做到这一点:

Get the number of days, weeks, and months, since Epoch in Java

串行器代码: -

@Override
    public byte[] serialize(String topic, T data) {
        try {
            byte[] result = null;

            if (data != null) {
                logger.debug("data='{}'" +  data);

                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                BinaryEncoder binaryEncoder =
                        EncoderFactory.get().binaryEncoder(byteArrayOutputStream, null);

                DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(data.getSchema());
                datumWriter.write(data, binaryEncoder);

                binaryEncoder.flush();
                byteArrayOutputStream.close();

                result = byteArrayOutputStream.toByteArray();
                byteArrayOutputStream.close();
                logger.debug("serialized data='{}'" +  DatatypeConverter.printHexBinary(result));
            }
            return result;
        } catch (IOException ex) {
            throw new SerializationException(
                    "Can't serialize data='" + data + "' for topic='" + topic + "'", ex);
        }
    }

desirializer代码: -

    @Override
    public T deserialize(String topic, byte[] data) {
        try {
            T result = null;

            if (data != null) {
                logger.debug("data='{}'" + DatatypeConverter.printHexBinary(data));

                DatumReader<GenericRecord> datumReader =
                        new SpecificDatumReader<>(targetType.newInstance().getSchema());
                Decoder decoder = DecoderFactory.get().binaryDecoder(data, null);

                result = (T) datumReader.read(null, decoder);
                logger.debug("deserialized data='{}'" + result);                
            }
            return result;
        } catch (Exception ex) {
            throw new SerializationException(
                    "Can't deserialize data '" + Arrays.toString(data) + "' from topic '" + topic + "'", ex);
        }
    }

架构文件: -

{"namespace": "com.test",
  "type": "record",
  "name": "Measures",
  "fields": [  
    {"name": "transactionDate", "type": ["int", "null"], "logicalType" : "date" }
   ]
}

这两个只是在生产者和消费者配置中被定义为序列化器和反序列化器类。

java apache-kafka avro
1个回答
0
投票

我没有使用Apace Avro和Apache Kafka,但也许这会有所帮助......

我可以发送和接收Apache Avro的日期类型

查看维基百科页面,Avro中没有定义Date类型:

Avro架构使用JSON定义。模式由基本类型(null,boolean,int,long,float,double,bytes和string)和复杂类型(记录,枚举,数组,映射,联合和固定)组成。

JSON also lacks date-time types

ISO 8601

在没有提供日期时间支持的情况下,我建议使用标准的ISO 8601格式将日期时间值序列化为文本。这些格式设计实用:易于通过机器解析,并且易于跨文化阅读,同时避免歧义。

对于仅日期值,格式为YYYY-MM-DD。 2018年1月23日将是2018-01-23

java.time

在解析/生成字符串时,java.time类默认使用ISO 8601格式。

LocalDate类表示没有时间且没有时区的仅日期值。

LocalDate.of( 2018 , Month.JANUARY , 23 )
         .toString()                              // Generating a string in standard format.

2018-01-23

LocalDate ld = LocalDate.parse( "2018-01-23" ) ;  // Parsing a string in standard format.

Count-from-epoch

我不建议从epoch reference跟踪日期时间值。但是如果你决定采用这种方式,那么java.time类可以提供帮助。

1970-01-01的纪元参考日期定义为常数LocalDate.EPOCH

获取该纪元参考后的天数。

long daysSinceEpoch = ld.toEpochDay() ;

17554

解析自纪元以来的天数。在1970-01-01结果中添加17,554天,结果是2018-01-23。

LocalDate ld = LocalDate.ofEpochDay( 17_554L ) ;  // 1970-01-01 + 17,554 days = 2018-01-23

你可以看到为什么我不推荐这种从纪元开始的方法:阅读和调试2018-01-23比解密17554容易得多。

Joda-Time

Apache Avro包括adapter class for Joda-Time类型(ticket AVRO-1672)。我不知道是否为java.time类型构建了这样的适配器。

Joda-Time项目是Java内置的java.time框架的前身。该项目现在处于维护模式,作者建议迁移到java.time类。


About java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,如java.util.DateCalendarSimpleDateFormat

现在在Joda-Timemaintenance mode项目建议迁移到java.time班。

要了解更多信息,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规格是JSR 310

您可以直接与数据库交换java.time对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目是未来可能添加到java.time的试验场。你可能会在这里找到一些有用的类,如IntervalYearWeekYearQuartermore

© www.soinside.com 2019 - 2024. All rights reserved.