简体   繁体   English

avro文件中存储的org.apache.kafka.connect.data.Decimal如何转换为python类型?

[英]How can a org.apache.kafka.connect.data.Decimal stored in an avro file be converted to a python type?

I am trying to interpret a Avro record stored by Debezium in Kafka , using Python我正在尝试使用Python解释DebeziumKafka中存储的Avro记录

           {
              "name": "id",
              "type": {
                "type": "bytes",
                "scale": 0,
                "precision": 64,
                "connect.version": 1,
                "connect.parameters": {
                  "scale": "0"
                },
                "connect.name": "org.apache.kafka.connect.data.Decimal",
                "logicalType": "decimal"
              }
            }

I am not sure to which Python 3 primitive type this corresponds to.我不确定这对应于哪个 Python 3 原始类型。 How can this value be deserialised?这个值如何反序列化?

Thanks in advance!提前致谢!

If you look at如果你看

https://insight.io/github.com/apache/kafka/blob/trunk/connect/api/src/main/java/org/apache/kafka/connect/data/Decimal.java https://insight.io/github.com/apache/kafka/blob/trunk/connect/api/src/main/java/org/apache/kafka/connect/data/Decimal.java

public static byte[] fromLogical(Schema schema, BigDecimal value) {
    if (value.scale() != scale(schema))
        throw new DataException("BigDecimal has mismatching scale value for given Decimal schema");
    return value.unscaledValue().toByteArray();
}

As you can see it uses BigDecimal and that is equivalent to Decimal in python如您所见,它使用 BigDecimal,相当于 Python 中的Decimal

What is the python for Java's BigDecimal? Java 的 BigDecimal 的 python 是什么?

So you should be looking for Decimal in this case.因此,在这种情况下,您应该寻找 Decimal。

Part 2 - Deserialization第 2 部分 - 反序列化

About the deserialization, I need feedback to update the answer.关于反序列化,我需要反馈来更新答案。 How do you do it for other fields as of now?到目前为止,您如何在其他领域做到这一点?

org.apache.kafka.connect.data.Decimal is base64 encoded byte representation of unscaled integer. org.apache.kafka.connect.data.Decimal是未缩放整数的 base64 编码字节表示。 In order to convert this value to Decimal , you need to decode base64 string to bytes, obtain integer and then scale it by parameters.scale value.为了将此值转换为Decimal ,您需要将 base64 字符串解码为字节,获取整数,然后通过parameters.scale值对其进行缩放。

This schema:这个架构:

{
  "type": "bytes",
  "name": "org.apache.kafka.connect.data.Decimal",
  "version": 1,
  "parameters": {
    "scale": "9",
    "connect.decimal.precision": "38"
  },
  "field": "amount"
}

Can be converted with this following snippet (try it on Pyfiddle ):可以使用以下代码段进行转换(在Pyfiddle尝试):

ctx = decimal.Context()
ctx.prec = 38  # connect.decimal.precision = 38
result = ctx.create_decimal(
    int.from_bytes(base64.b64decode("GZ6ZFQvYpA=="), byteorder='big')
) / 10 ** 9  # scale = 9

When I use other answer for negative number, it give wrong result.当我对负数使用其他答案时,它会给出错误的结果。 for example -20.62 numeric is converted to "+CA=" by debezium to kafka例如 -20.62 数字被 debezium 转换为“+CA=”到 kafka

I find the solution from below link and I change like this.我从下面的链接中找到了解决方案,然后像这样更改。

import decimal
import base64
def big_decimal_to_decimal(big_decimal, scale, precision):
    bytes_val = base64.decodebytes(big_decimal.encode())
    bval = "".join("{0:08b}".format(c) for c in bytes_val)
    intval = int(bval, 2)
    if bytes_val[0] & 0x70 != 0:
        intval -= int('1' + '00' * len(bytes_val), 16)
    return intval/(10**scale)

link: Decode base64 encoded byte array to (negative) decimal value (Java to Python)链接: 将 base64 编码字节数组解码为(负)十进制值(Java 到 Python)

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

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