如何在.NET Core 3.1中为属性级Newtonsoft JsonConverter注入依赖
解决方案
实现原理
默认JsonConverterAttribute会调用转换器的无参构造函数完成实例化,无法自动从DI容器获取依赖服务;你之前尝试的旧方案使用了已过时的MvcJsonOptions(仅适配ASP.NET Core 2.x),.NET Core 3.1默认使用System.Text.Json,启用Newtonsoft.Json后需使用MvcNewtonsoftJsonOptions做配置。
本方案通过自定义ContractResolver,在属性构建阶段检测指定转换器特性,直接从当前请求的DI容器中获取已经完成依赖注入的转换器实例赋值给对应属性,无需全局注册转换器,仅标注了对应特性的属性才会触发逻辑,完全匹配你的需求。
具体实现步骤
步骤1:注册基础服务
在Startup.cs的ConfigureServices方法中注册所需服务:
// 注册HttpContext访问器,用于获取当前请求的DI容器 services.AddHttpContextAccessor(); // 注册你的业务服务 services.AddScoped<IMyService, MyServiceImpl>(); // 注册自定义JsonConverter,生命周期可根据依赖服务调整 services.AddTransient<HelloWorldCustomConverter>();
步骤2:实现支持DI的ContractResolver
using System.Reflection; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; public class DiSupportContractResolver : DefaultContractResolver { private readonly IHttpContextAccessor _httpContextAccessor; public DiSupportContractResolver(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var property = base.CreateProperty(member, memberSerialization); // 读取属性上的JsonConverter特性 var converterAttr = member.GetCustomAttribute<JsonConverterAttribute>(); if (converterAttr == null) return property; // 匹配需要支持DI的转换器类型,多转换器可扩展多个判断分支 if (converterAttr.ConverterType == typeof(HelloWorldCustomConverter)) { // 从当前请求的服务容器中获取已注入完成的转换器实例 var converter = _httpContextAccessor.HttpContext?.RequestServices.GetRequiredService<HelloWorldCustomConverter>(); if (converter != null) { property.Converter = converter; } } return property; } }
步骤3:配置Newtonsoft.Json选项
using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Newtonsoft.Json; public class DiJsonOptionsSetup : IConfigureOptions<MvcNewtonsoftJsonOptions> { private readonly IHttpContextAccessor _httpContextAccessor; public DiJsonOptionsSetup(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public void Configure(MvcNewtonsoftJsonOptions options) { // 替换默认的ContractResolver options.SerializerSettings.ContractResolver = new DiSupportContractResolver(_httpContextAccessor); } }
步骤4:注册配置到容器
在Startup.cs的ConfigureServices方法中补充配置注册,必须先启用Newtonsoft.Json:
services.AddControllers() // 启用Newtonsoft.Json(.NET Core 3.1默认使用System.Text.Json,需显式启用) .AddNewtonsoftJson(); // 注册自定义Json配置 services.AddSingleton<IConfigureOptions<MvcNewtonsoftJsonOptions>, DiJsonOptionsSetup>();
验证效果
你原有代码完全不需要修改:HelloWorldCustomConverter的依赖注入逻辑保留,MyClass的Details属性上的[JsonConverter(typeof(HelloWorldCustomConverter))]特性也无需修改,仅该属性会触发带DI注入的转换器逻辑,不会全局生效。
注意事项
- 若存在多个需要支持DI的转换器,仅需在
CreateProperty方法中补充对应类型判断即可 - 若在非请求场景下(如后台任务)序列化对象,
HttpContext为空,需手动创建DI Scope获取转换器实例,再手动指定到序列化设置的Converters集合中 - 需确保已安装对应版本的
Microsoft.AspNetCore.Mvc.NewtonsoftJsonNuGet包
内容的提问来源于stack exchange,提问作者Sunny Sharma
相关产品推荐
相关产品推荐

