ABP Framework全局自定义JsonConverter配置不生效如何解决
ABP Framework全局替换默认枚举JSON转换器方案
问题表现
需要在ABP Framework中实现自定义JSON转换器,替换框架默认提供的AbpStringToEnumConverter。最初尝试通过修改JsonSerializerOptions.Converters实现全局替换的代码未生效,实现代码如下:
public override void ConfigureServices(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); var hostingEnvironment = context.Services.GetHostingEnvironment(); ConfigureEnumCodeStringConverter(); // ...其他服务配置 } private void ConfigureEnumCodeStringConverter() { Configure<AbpSystemTextJsonSerializerOptions>(options => { var stringToEnumFactory = options.JsonSerializerOptions.Converters.Single(x => x.GetType() == typeof(AbpStringToEnumFactory)); options.JsonSerializerOptions.Converters.Remove(stringToEnumFactory); options.JsonSerializerOptions.Converters.Add(new EnumToCodeFactory()); }); }
在DTO属性上单独添加[JsonConverter]特性时自定义转换器可以正常工作,但逐属性标注的方式维护成本过高,需要实现全局生效的配置,特性使用示例如下:
[Required] [JsonConverter(typeof(EnumToCodeConverter<Gender>))] public Gender Gender { get; set; }
失效原因
配置不生效的核心原因有两点:
- 配置执行时机错误:普通
Configure<AbpSystemTextJsonSerializerOptions>的执行顺序早于ABP框架内置注册默认AbpStringToEnumFactory的流程,提前移除的默认转换器会被框架后续的默认配置重新添加回集合。 - 配置覆盖不全:ABP中存在两份独立的JSON序列化配置,一份是框架内部使用的
AbpSystemTextJsonSerializerOptions,另一份是给MVC接口入参出参用的Microsoft.AspNetCore.Mvc.JsonOptions,只修改前者不会覆盖接口请求响应的序列化逻辑。同时System.Text.Json按转换器集合的顺序匹配优先级,后添加的转换器优先级低于排在前面的默认转换器。
正确实现方式
- 将原来的
Configure替换为PostConfigure,保证配置逻辑在ABP所有默认JSON配置执行完成后再运行,同时将自定义转换器插入到集合首位保证优先级最高:
private void ConfigureEnumCodeStringConverter() { // 配置ABP内部序列化使用的选项 PostConfigure<AbpSystemTextJsonSerializerOptions>(options => { var defaultEnumFactory = options.JsonSerializerOptions.Converters .FirstOrDefault(x => x.GetType() == typeof(AbpStringToEnumFactory)); if (defaultEnumFactory != null) { options.JsonSerializerOptions.Converters.Remove(defaultEnumFactory); } // 插入到集合首位,保证优先匹配 options.JsonSerializerOptions.Converters.Insert(0, new EnumToCodeFactory()); }); // 同步配置MVC接口序列化使用的选项 PostConfigure<Microsoft.AspNetCore.Mvc.JsonOptions>(mvcJsonOptions => { var defaultEnumFactory = mvcJsonOptions.JsonSerializerOptions.Converters .FirstOrDefault(x => x.GetType() == typeof(AbpStringToEnumFactory)); if (defaultEnumFactory != null) { mvcJsonOptions.JsonSerializerOptions.Converters.Remove(defaultEnumFactory); } mvcJsonOptions.JsonSerializerOptions.Converters.Insert(0, new EnumToCodeFactory()); }); }
- 配置完成后不需要在任何DTO属性上额外添加
[JsonConverter]特性,所有枚举类型的序列化、反序列化都会默认走自定义的EnumToCodeFactory逻辑。
内容的提问来源于stack exchange,提问作者Enes Köse
相关产品推荐
相关产品推荐

