You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Azure Service Bus接收JSON时尾部出现重复字段问题求助

解决Azure Service Bus接收JSON时尾部字段重复的问题

兄弟,你的问题根源在于读取消息体时的字节数组处理不当!

问题原因分析

你用了固定大小(200字节)的byte[] b来循环读取输入流,每次读取后直接把整个数组转成字符串:

s = new String(b);

当最后一次读取的字节数小于200时,数组里还残留着上一次读取的剩余字节,这些残留内容会被一起转成字符串,就导致了你看到的JSON末尾重复字段的问题。举个例子:假设最后一次只读到50字节,那数组里剩下的150字节是上一次读取的旧数据,直接转字符串就会把这些旧数据也带出来。

解决方案

方案1:正确处理每次读取的有效字节长度

StringBuilder拼接每次读取的有效字节块,只转换实际读到的字节数,而不是整个数组:

import java.nio.charset.StandardCharsets;

// ...

if (message != null && message.getMessageId() != null) {
    System.out.println("MessageID: " + message.getMessageId());
    System.out.print("From queue: ");
    byte[] b = new byte[200];
    StringBuilder messageBuilder = new StringBuilder();
    int numRead = message.getBody().read(b);
    System.out.println("numread--"+numRead);
    while (-1 != numRead) {
        // 仅转换本次读取的numRead个字节,避免残留旧数据
        String chunk = new String(b, 0, numRead, StandardCharsets.UTF_8);
        messageBuilder.append(chunk);
        numRead = message.getBody().read(b);
    }
    String fullJson = messageBuilder.toString().trim();
    System.out.println(fullJson);
}

这里额外指定了StandardCharsets.UTF_8编码,避免不同环境下默认编码不一致导致的乱码问题,更稳妥。

方案2:用工具类一次性读取整个流(更简洁)

如果你的项目是Java 9及以上,可以直接用InputStream.readAllBytes()一次性读取所有字节,省掉循环处理:

import java.nio.charset.StandardCharsets;

// ...

if (message != null && message.getMessageId() != null) {
    System.out.println("MessageID: " + message.getMessageId());
    System.out.print("From queue: ");
    byte[] allBytes = message.getBody().readAllBytes();
    String fullJson = new String(allBytes, StandardCharsets.UTF_8).trim();
    System.out.println(fullJson);
}

如果项目里依赖了Apache Commons IO库,也可以用IOUtils.toString()来简化:

import org.apache.commons.io.IOUtils;
import java.nio.charset.StandardCharsets;

// ...

if (message != null && message.getMessageId() != null) {
    System.out.println("MessageID: " + message.getMessageId());
    System.out.print("From queue: ");
    String fullJson = IOUtils.toString(message.getBody(), StandardCharsets.UTF_8).trim();
    System.out.println(fullJson);
}

这种方式完全不用手动处理流的循环读取,代码更简洁,出错概率更低。

额外优化建议

发送消息时其实可以直接传入对象而非JSON字符串,让BrokeredMessage自动序列化,接收时也可以直接反序列化为对象,这样能避免手动处理JSON字符串的麻烦:

// 发送端
YourObject obj = new YourObject();
BrokeredMessage message = new BrokeredMessage(obj);

// 接收端
YourObject receivedObj = message.getBody(YourObject.class);

如果必须用JSON字符串,也建议用Jackson/Gson等库来序列化/反序列化,比手动处理字符串更可靠。

内容的提问来源于stack exchange,提问作者nikita kakraniya

火山引擎 最新活动