[英]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将无法帮助您(就像您省略了逻辑类型相关字段一样)。
文件说明:
十进制逻辑类型注释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)序列化器是为所有逻辑类型提供的(请参阅Conversion
和Conversions
),并且转换已插入GenericData。 这意味着当您询问字段的值时,您将收到BigDecimal
实例。 如果正确注释字段,ReflectData似乎也能够产生预期的模式(但是AFAIK没有为逻辑类型创建专用注释)。
但是,我不清楚是否已更新avro-compiler / codegen以支持逻辑类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.