繁体   English   中英

如何从ByteBuffer转换为Avro字节?

[英]How do I convert from ByteBuffer to Avro bytes?

我有一个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

文件说明:

十进制逻辑类型注释Avro字节或固定类型。 字节数组必须包含big-endian字节顺序中未缩放的整数值的二进制补码表示 比例是固定的,并使用属性指定。

可以用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,则不会免费提供。 您必须编写自己的(de)序列化程序,代码生成和反映不支持此构造。 使用它的唯一原因是遵守规范,并希望未来的Avro版本能让您的生活更轻松。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM