java - 如何从 ByteBuffer 转换为 Avro 字节?

标签 java avro

我有一个 avro 模式,其中包含以下字段之一

{
  "name" : "currency",
  "type" : ["null","bytes"],
  "logicalType": "decimal",
  "precision": 9,
  "scale": 4
},

我运行了 avro-tools jar 来创建 java 文件来表示模式。这产生了如下所示的属性:public java.nio.ByteBuffer currency;

在我的代码的其他地方,我将使用 BigDecimal 类型的货币值。

在创建此类的实例时,如何将 BigDecimal 值转换为预期的 ByteBuffer?我可以只使用 ByteBuffer.toByteArray() 还是我需要做任何特殊的事情来确保它与 avro(以及可能正在读取数据的 Impala 等其他工具)兼容?

最佳答案

让我们从免责声明开始。虽然“逻辑类型”部分出现在大约 2014 年的规范中,但它还不受任何 Avro Java 版本的支持。

您可以决定声明一个符合规范的模式并将正确的字节放入该字段,但 Avro Java 不会帮助您(这与您省略逻辑类型相关字段完全一样)。

如何将 BigDecimal 值转换为预期的 ByteBuffer

文档指出:

A decimal logical type annotates Avro bytes or fixed types. The byte array must contain the two's-complement representation of the unscaled integer value in big-endian byte order. The scale is fixed, and is specified using an attribute.

可以用 Java 翻译为(从 Avro 1.8.0-rc2 复制粘贴):

public ByteBuffer toBytes(BigDecimal value, Schema schema, LogicalType type)
{
    int scale = ((LogicalTypes.Decimal) type).getScale();
    if (scale != value.scale()) {
        throw new AvroTypeException("Cannot encode decimal with scale " +
          value.scale() + " as scale " + scale);
    }

    return ByteBuffer.wrap(value.unscaledValue().toByteArray());
}

您可以阅读 BigDecimal 和 BigInteger 的 Javadoc 来检查 value.unscaledValue().toByteArray() 是否符合规范。

以类似的方式,您可以使用以下代码反序列化该字段:return new BigDecimal(new BigInteger(bytes), scale);

你应该使用逻辑类型吗?

如前言所述,如果您使用的是 Avro 1.7,则不会免费提供任何东西。您必须编写自己的(反)序列化程序,代码生成和反射(reflect)不支持此构造。使用它的唯一原因是遵守规范,并希望 future 的 Avro 版本能让您的生活更轻松。

Avro 1.8.0-rc2 包含一些代码来支持逻辑类型并引入新的逻辑类型。似乎为所有逻辑类型提供了(反)序列化器(参见 ConversionConversions)并且转换已插入 GenericData。这意味着当您询问该字段的值时,您将收到一个 BigDecimal 实例。如果您正确注释该字段,ReflectData 似乎也能够生成预期的模式(但 AFAIK 没有为逻辑类型创建专用注释)。

但是,我不清楚 avro-compiler/codegen 是否已更新以支持逻辑类型。

关于java - 如何从 ByteBuffer 转换为 Avro 字节?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34866793/

相关文章:

hadoop - 使用架构文件创建一个 Parquet 支持的 Hive 表

java - Avro - java.io.IOException : Not a data file

java - 创建返回字符串中重复字符的函数

java - 扫描命名空间中尚未导入的类

java - Avro 逻辑类型 'date',默认为空值

java - 从 kafka 流和 Avro 反序列化同一类时出现 ClassCastException

java - 如何将 "org.apache.avro.generic.GenericRecord"转换为 "java.util.Map"?

java - 使用 OkHttp 获取 Http 状态码

java - 如何直接向 parking 场队列发送消息、防止重新排队并退出程序流程?

java - 有没有办法在 null 时自动初始化变量