设置Json反序列化字典为Service Bus消息ApplicationProperties时发送失败
Azure Service Bus ApplicationProperties 序列化问题解决方案
问题核心
使用System.Text.Json反序列化JSON得到<string, object>字典时,字典值实际是JsonElement类型,而Azure Service Bus的ApplicationProperties仅支持.NET原生基本类型(如string、int、bool、DateTime等),不兼容JsonElement,导致调用SendMessageAsync时抛出System.Runtime.Serialization.SerializationException。
通用解决方案
无需逐个类型判断,通过一个通用转换方法将JsonElement转换为对应的.NET原生类型即可:
1. 编写类型转换方法
private static object ConvertJsonElementToNativeType(JsonElement element) { return element.ValueKind switch { JsonValueKind.String => element.GetString(), JsonValueKind.Number => element.TryGetInt64(out var longVal) ? longVal : element.GetDouble(), JsonValueKind.True => true, JsonValueKind.False => false, JsonValueKind.Null => null, JsonValueKind.Array => element.EnumerateArray().Select(ConvertJsonElementToNativeType).ToList(), JsonValueKind.Object => element.EnumerateObject().ToDictionary(kv => kv.Name, kv => ConvertJsonElementToNativeType(kv.Value)), _ => element.ToString() }; }
2. 转换字典值后赋值给ApplicationProperties
在将反序列化得到的字典赋值给消息属性前,先处理每个值:
var paramsDict = GetParams(); // 你的反序列化方法返回的字典 if (paramsDict is not null) { foreach (var kvp in paramsDict) { message.ApplicationProperties[kvp.Key] = kvp.Value is JsonElement jsonElement ? ConvertJsonElementToNativeType(jsonElement) : kvp.Value; } }
替代方案(反序列化时直接处理)
如果不想事后转换,也可以在反序列化阶段直接配置JsonSerializerOptions,让object类型直接序列化为原生类型:
var options = new JsonSerializerOptions { Converters = { new JsonObjectToPrimitiveConverter() } }; var paramsDict = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonPayload, options);
其中自定义转换器实现如下:
public class JsonObjectToPrimitiveConverter : JsonConverter<object> { public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return reader.TokenType switch { JsonTokenType.String => reader.GetString(), JsonTokenType.Number => reader.TryGetInt64(out var l) ? l : reader.GetDouble(), JsonTokenType.True => true, JsonTokenType.False => false, JsonTokenType.Null => null, JsonTokenType.StartArray => JsonSerializer.Deserialize<List<object>>(ref reader, options), JsonTokenType.StartObject => JsonSerializer.Deserialize<Dictionary<string, object>>(ref reader, options), _ => JsonDocument.ParseValue(ref reader).RootElement.Clone() }; } public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) { JsonSerializer.Serialize(writer, value, value.GetType(), options); } }
内容的提问来源于stack exchange,提问作者binga58
相关产品推荐
相关产品推荐

