如何序列化包含BinaryData类型消息体的ServiceBusReceivedMessage对象
问题原因
你遇到的序列化后Body为空的问题根因有两点:
ServiceBusReceivedMessage的Body属性类型为BinaryData,Newtonsoft.Json默认序列化该类型时,不会自动读取其底层承载的字节/文本内容,只会序列化无关的空结构- 部分版本的Azure.Messaging.ServiceBus库中,
ServiceBusReceivedMessage的Body属性对反射序列化的访问做了限制,导致默认序列化逻辑无法读取到实际内容
高效解决方案
方案1:使用自定义JsonConverter(改动最小,兼容现有逻辑)
编写针对BinaryData类型的序列化转换器,序列化时自动提取实际内容,无需修改原有业务流程:
public class BinaryDataJsonConverter : JsonConverter<BinaryData> { public override void WriteJson(JsonWriter writer, BinaryData value, JsonSerializer serializer) { // 如果消息体是文本内容直接输出字符串;如果是二进制内容可改为输出Convert.ToBase64String(value.ToArray()) writer.WriteValue(value.ToString()); } public override BinaryData ReadJson(JsonReader reader, Type objectType, BinaryData existingValue, bool hasExistingValue, JsonSerializer serializer) { var value = reader.Value?.ToString(); return value == null ? null : BinaryData.FromString(value); } }
调用序列化方法时传入转换器即可:
foreach (ServiceBusReceivedMessage receivedMessage in receivedMessages) { var fullMessage = JsonConvert.SerializeObject(receivedMessage, new BinaryDataJsonConverter()); }
该方案性能损耗极低,不需要额外对象拷贝,全程仅在序列化阶段处理Body内容。
方案2:手动映射到自定义DTO(可控性最高,适合生产环境长期使用)
如果需要定制更多序列化规则,建议自定义消息传输类,手动映射所有属性,避免类库内部版本变更影响序列化结果:
public class CustomServiceBusMessage { public string Body { get; set; } public string MessageId { get; set; } public string SessionId { get; set; } public DateTimeOffset EnqueuedTime { get; set; } // 按需添加所有需要用到的ServiceBusReceivedMessage属性 } // 映射逻辑 foreach (ServiceBusReceivedMessage receivedMessage in receivedMessages) { var customMsg = new CustomServiceBusMessage { Body = receivedMessage.Body.ToString(), MessageId = receivedMessage.MessageId, EnqueuedTime = receivedMessage.EnqueuedTime, // 其余属性逐一赋值 }; var fullMessage = JsonConvert.SerializeObject(customMsg); }
注意事项
如果消息体存储的是非文本的二进制内容,不要使用ToString(),改为转Base64字符串序列化即可:Body = Convert.ToBase64String(receivedMessage.Body.ToArray())
内容的提问来源于stack exchange,提问作者HobbyLobbyVS
相关产品推荐
相关产品推荐

