如何解决Azure EventGridEvent忽略NewtonSoft.Json序列化配置的问题
新版Azure.Messaging.EventGrid SDK中的EventGridPublisherClient默认使用System.Text.Json完成序列化工作,完全不会识别Newtonsoft.Json(Json.NET)体系下的[JsonProperty]、[JsonConverter]等特性,也不会读取你全局给Newtonsoft.Json配置的序列化规则,这就是属性名映射、枚举转字符串配置全部失效的核心原因。
至于[DataMember]特性不生效,是因为System.Text.Json默认不会读取该特性的配置,除非你手动开启对应支持。
你可以根据自己的项目场景选以下任意一种方案:
方案1:替换为System.Text.Json对应特性(零额外代码,最简便)
如果项目没有强依赖Newtonsoft.Json的特殊序列化规则,直接把实体类上的Newtonsoft特性替换为System.Text.Json的对应特性即可,不需要修改其他发送逻辑:
using System.Text.Json.Serialization; public class CuData { public enum CancellationTypes { Regular, Special, Relocation } [JsonPropertyName("type")] [JsonConverter(typeof(JsonStringEnumConverter))] public CancellationTypes CancellationType { get; set; } }
注意这里的JsonStringEnumConverter来自System.Text.Json.Serialization命名空间,不要和Newtonsoft下的同名类混淆,修改后默认序列化输出就和预期的{"type":"Regular"}完全一致。
方案2:配置客户端使用Newtonsoft.Json序列化(适合全局统一用Newtonsoft的项目)
如果项目全链路都用Newtonsoft.Json做序列化,不想修改现有实体类上的特性,可以给EventGrid客户端注入自定义序列化器,让它用Newtonsoft的规则处理payload:
- 先实现SDK提供的
ObjectSerializer抽象类,封装Newtonsoft的序列化逻辑:
using Azure.Core.Serialization; using Newtonsoft.Json; public class NewtonsoftJsonEventGridSerializer : ObjectSerializer { private readonly JsonSerializerSettings _jsonSettings; public NewtonsoftJsonEventGridSerializer(JsonSerializerSettings settings = null) { _jsonSettings = settings ?? new JsonSerializerSettings(); } public override object Deserialize(Stream stream, Type returnType, CancellationToken cancellationToken) { using var streamReader = new StreamReader(stream); using var jsonReader = new JsonTextReader(streamReader); return JsonSerializer.Create(_jsonSettings).Deserialize(jsonReader, returnType); } public override async ValueTask<object> DeserializeAsync(Stream stream, Type returnType, CancellationToken cancellationToken) { using var streamReader = new StreamReader(stream); using var jsonReader = new JsonTextReader(streamReader); return await Task.FromResult(JsonSerializer.Create(_jsonSettings).Deserialize(jsonReader, returnType)); } public override void Serialize(Stream stream, object value, Type inputType, CancellationToken cancellationToken) { using var streamWriter = new StreamWriter(stream, leaveOpen: true); using var jsonWriter = new JsonTextWriter(streamWriter); JsonSerializer.Create(_jsonSettings).Serialize(jsonWriter, value, inputType); jsonWriter.Flush(); } public override async ValueTask SerializeAsync(Stream stream, object value, Type inputType, CancellationToken cancellationToken) { using var streamWriter = new StreamWriter(stream, leaveOpen: true); using var jsonWriter = new JsonTextWriter(streamWriter); JsonSerializer.Create(_jsonSettings).Serialize(jsonWriter, value, inputType); await jsonWriter.FlushAsync(cancellationToken); } }
- 初始化
EventGridPublisherClient时,传入配置了自定义序列化器的客户端选项:
var clientOptions = new EventGridPublisherClientOptions { Serializer = new NewtonsoftJsonEventGridSerializer(new JsonSerializerSettings { // 这里可以放项目全局的Newtonsoft配置,比如命名策略、自定义转换器等 Converters = { new StringEnumConverter() } }) }; // 替换为你自己的EventGrid主题终结点、访问密钥 _client = new EventGridPublisherClient( new Uri(_configuration.TopicEndpoint), new Azure.AzureKeyCredential(_configuration.TopicKey), clientOptions );
配置完成后,原来写在实体类上的所有Newtonsoft特性、全局序列化规则都会正常生效。
方案3:提前手动序列化payload(侵入性最低,适合少量发送场景)
如果不想改客户端配置,也不想修改实体类代码,可以在构造EventGrid事件前,先用Newtonsoft把payload序列化成符合要求的JSON,再转成JsonDocument传入,直接绕过SDK的默认序列化逻辑:
public async Task SendMsg(string eventType, string dataVersion, object payload) { // 按自定义的Newtonsoft规则序列化payload var serializedPayload = JsonConvert.SerializeObject(payload, new StringEnumConverter()); // 解析为JsonDocument传入EventGridEvent using var jsonDoc = JsonDocument.Parse(serializedPayload); var gridEvent = new EventGridEvent("myevent", eventType, dataVersion, jsonDoc.RootElement) { Topic = _configuration.Topic }; await _client.SendEventAsync(gridEvent); }
额外提示:当前代码里把
CancellationTypes枚举定义在CuData类内部,虽然不会直接导致序列化失效,但不符合C#类型定义的常规实践,容易引发其他引用、序列化场景下的异常,建议把枚举定义移到类外层的命名空间下。
内容的提问来源于stack exchange,提问作者Ole Albers

