在 DataWeave 中处理十六进制的负数

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

我正在努力淘汰 Python Kafka Consumer 以使用 Mule runtime 代替。

我遇到了 DataWeave 和按位运算符的阻塞,特别是如何处理负十六进制数。

目前,我的 Kafka/Debezium 生产者提供以下值

+PB34g==
应该解码为
-118.458398

使用 Python,我可以使用 Two's Complement 进行移位并转换为负数。但是,我还没有找到可比的 DataWeave 解决方案。

我们用这个函数解码Base64值,然后用下面的函数转换成整数。

    # decode the integer
    # and handle negative values
    def _b64_to_int(self, value):
        num = int.from_bytes(base64.b64decode(value), 'big')
        # now check the sign
        # and if negative, take 2's complement
        # TODO: works, but isn't 64-bit safe
        if num & (1 << 31):
            num -= int('1' + '00' * 4, 16)
        #print(f"{value} = {num}")
        return num

我可以在 Java 类中处理这个,但如果可能的话我更愿意使用 DataWeave。

    # and handle negative values
    def _b64_to_int(self, value):
        num = int.from_bytes(base64.b64decode(value), 'big')
        # now check the sign
        # and if negative, take 2's complement
        # TODO: works, but isn't 64-bit safe
        if num & (1 << 31):
            num -= int('1' + '00' * 4, 16)
        #print(f"{value} = {num}")
        return num

我有以下 DataWeave 将 Base64 转换为数字。我发现这篇文章创建了自定义按位函数,但它们没有处理负值。

%dw 2.0
output application/json
import * from dw::core::Binaries
fun to_number(b64) = dw::core::Numbers::fromHex(toHex(fromBase64(b64)))
fun to_decimal(num, scale) = to_number(num) as Number / pow(10, scale)
---
to_decimal("+PB34g==", 5)
mule dataweave mule-studio mulesoft mule4
1个回答
0
投票

我将逻辑从 Python 代码片段转换为 DataWeave,并从您的 DataWeave 脚本中添加了

to_decimal()
函数以获得预期结果。

%dw 2.0
output application/json
import * from dw::core::Binaries
import * from dw::core::Numbers

var leftshift_1_31=fromBinary("10000000000000000000000000000000")
var hex_100000000="0100000000"

fun AND(bin1, bin2) = do {
    var b1=getBinary(bin1, 64)
    var b2=getBinary(bin2, 64)
    ---
    fromBinary(b1 map ($ as Number * b2[$$] as Number) reduce ($$++$))
}

fun getBinary(i: Number, size: Number) = do {
    var b = toBinary(i)
    ---
    dw::core::Strings::leftPad(b, size, '0') splitBy ''
}

fun to_number(b64) = do {
    var result = dw::core::Numbers::fromHex(toHex(fromBase64(b64)))
    ---
    if ((AND(result, leftshift_1_31)==0))
        result 
    else
        result - dw::core::Numbers::fromHex(hex_100000000) 
}

fun to_decimal(num, scale) = to_number(num) as Number / pow(10, scale)
---
to_decimal("+PB34g==", 6)

输出:

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