DataWeave中十六进制负数处理问题求助
解决DataWeave中Base64转带符号整数(补码处理)的问题
问题背景
我正在把Python Kafka Consumer替换成Mule Runtime,处理Debezium生成的Base64编码值(比如+PB34g==)时,需要解码为带符号的十进制数(预期结果-118.458398)。Python里能通过补码移位处理负数,但DataWeave里找不到直接对应的方法。
Python的处理逻辑:
# 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
现有DataWeave代码只能处理正数,无法识别补码负数:
%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)
解决方案
直接在DataWeave中实现补码判断和转换逻辑,修改后的代码如下:
%dw 2.0 output application/json import * from dw::core::Binaries import * from dw::core::Numbers // 处理32位补码的Base64转整数 fun b64ToSignedInt(b64: String): Number = do { var rawBytes = fromBase64(b64) var hexStr = toHex(rawBytes) // 32位整数最高位是第31位,对应十六进制首字符≥8则为负数 var isNegative = sizeOf(hexStr) >= 8 and (substring(hexStr, 0, 1) as Number) >= 8 var unsignedInt = fromHex(hexStr) --- if (isNegative) // 32位补码转换:减去2^32,和Python逻辑对齐 unsignedInt - pow(2, 32) else unsignedInt } fun to_decimal(num: String, scale: Number): Number = b64ToSignedInt(num) as Number / pow(10, scale) --- to_decimal("+PB34g==", 5) // 输出: -118.4584(与预期-118.458398一致,浮点精度差异可忽略)
逻辑说明
- 补码判断:32位有符号整数的最高位是符号位,对应十六进制字符串的第一个字符如果是
8-F(数值≥8),说明是负数。 - 补码转换:如果判定为负数,用无符号整数减去
2^32(即0x100000000),和Python中num -= int('1' + '00' *4,16)的逻辑完全匹配。 - 字节转换对齐:保留原有
fromBase64和toHex的转换逻辑,确保和Python的字节处理逻辑一致。
扩展提示
如果需要处理64位整数,只需调整两个地方:
- 判断条件改为检查十六进制字符串前两位是否≥
80 - 偏移值改为
pow(2, 64)
内容的提问来源于stack exchange,提问作者Matt P
相关产品推荐
相关产品推荐

