NET 4.6.1下Windows.Azure.ServiceBus 5.2.0反序列化消息体失败问题
问题根因
Windows.Azure.ServiceBus库的BrokeredMessage默认会对传入的字符串类型载荷使用WCF二进制DataContract格式做封装,读取到的前缀@string3http://schemas.microsoft.com/2003/10/Serialization/和乱码为封装头,后半段为目标JSON字符串。- 触发反序列化报错的核心原因是消息流被提前读取后,
Position指针移动到了末尾,XmlDictionaryReader读取时无有效内容,因此抛出找不到元素的异常。
解决方案
方案1:修复现有反序列化逻辑(优先尝试,无需修改发送端)
读取流之前先重置流位置即可,修改后代码如下:
Stream bodyStream = brokeredMessage.GetBody<Stream>(); // 关键:重置流指针到起始位置 bodyStream.Position = 0; // 先读一遍原始内容判断前缀,leaveOpen设为true避免读完自动释放流 using var tempReader = new StreamReader(bodyStream, Encoding.UTF8, leaveOpen: true); string rawContent = tempReader.ReadToEnd(); if (rawContent.StartsWith("@")) { // 再次重置流位置给反序列化用 bodyStream.Position = 0; DataContractSerializer serializer = new(typeof(string)); using XmlDictionaryReader xmlDictionaryReader = XmlDictionaryReader.CreateBinaryReader(bodyStream, XmlDictionaryReaderQuotas.Max); string messageBody = (string)serializer.ReadObject(xmlDictionaryReader); // 此处拿到的messageBody即为目标JSON字符串 }
方案2:直接截取JSON内容(无需反序列化,兼容异常场景)
如果不需要严格走序列化流程,可以直接从原始内容中截取JSON部分,代码更简单:
Stream bodyStream = brokeredMessage.GetBody<Stream>(); bodyStream.Position = 0; using var reader = new StreamReader(bodyStream, Encoding.UTF8); string rawContent = reader.ReadToEnd(); // 找到第一个JSON起始符的位置,截取后面所有内容 int jsonStart = rawContent.IndexOf('{'); if (jsonStart >= 0) { string jsonBody = rawContent.Substring(jsonStart); // 直接拿到可用的JSON字符串 }
方案3:修改发送端逻辑(彻底规避序列化封装问题)
如果可以调整发送端代码,直接把JSON转成字节数组发送,就不会触发BrokeredMessage的默认字符串序列化封装:
发送端代码
string json = JsonSerializer.Serialize(yourPayload); byte[] jsonBytes = Encoding.UTF8.GetBytes(json); // 直接传入字节数组构造BrokeredMessage BrokeredMessage message = new BrokeredMessage(jsonBytes);
接收端代码
byte[] receivedBytes = brokeredMessage.GetBody<byte[]>(); string jsonBody = Encoding.UTF8.GetString(receivedBytes); // 无需任何额外处理直接拿到JSON
内容的提问来源于stack exchange,提问作者Orbittman
相关产品推荐
相关产品推荐

