如何在Json.NET的JsonConverter的ReadJson方法中注入服务
解决方案:在特性指定的JsonConverter中访问服务(Newtonsoft.Json 13.0.1)
由于通过[JsonConverter]特性指定的转换器默认会用无参构造实例化,无法直接注入服务,这里提供两种可行的实现方式:
方法一:利用JsonSerializer的DependencyResolver
通过自定义IDependencyResolver让Newtonsoft.Json在创建转换器时从服务容器中获取实例,支持带参构造的转换器。
1. 实现带服务依赖的自定义转换器
public class MySpecialConverter : JsonConverter<IMyInterface> { private readonly IMyService _myService; // 注入服务的构造函数 public MySpecialConverter(IMyService myService) { _myService = myService ?? throw new ArgumentNullException(nameof(myService)); } public override IMyInterface ReadJson(JsonReader reader, Type objectType, IMyInterface existingValue, bool hasExistingValue, JsonSerializer serializer) { // 直接使用注入的服务 var jsonObj = JObject.Load(reader); var typeId = jsonObj["TypeId"].Value<int>(); var targetInstance = _myService.CreateInstance(typeId); // 填充实例属性 serializer.Populate(jsonObj.CreateReader(), targetInstance); return targetInstance; } public override void WriteJson(JsonWriter writer, IMyInterface value, JsonSerializer serializer) { // 序列化逻辑示例 writer.WriteStartObject(); writer.WritePropertyName("TypeId"); writer.WriteValue(_myService.GetTypeId(value.GetType())); serializer.Serialize(writer, value); writer.WriteEndObject(); } }
2. 实现自定义DependencyResolver
public class ServiceDependencyResolver : IDependencyResolver { private readonly IServiceProvider _serviceProvider; public ServiceDependencyResolver(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public object GetService(Type serviceType) { return _serviceProvider.GetService(serviceType); } public IEnumerable<object> GetServices(Type serviceType) { return _serviceProvider.GetServices(serviceType); } }
3. 配置并使用JsonSerializerSettings
// 假设已通过DI容器获取到IServiceProvider实例 var settings = new JsonSerializerSettings { DependencyResolver = new ServiceDependencyResolver(serviceProvider) }; // 反序列化示例 var result = JsonConvert.DeserializeObject<IMyInterface>(jsonString, settings);
方法二:自定义ContractResolver替换转换器实例
通过重写契约解析器,将特性指定的无参转换器替换为从服务容器中获取的带参实例。
1. 实现自定义ContractResolver
public class InjectableContractResolver : DefaultContractResolver { private readonly IServiceProvider _serviceProvider; public InjectableContractResolver(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } protected override JsonContract CreateContract(Type objectType) { var contract = base.CreateContract(objectType); // 检查当前类型是否标记了目标转换器特性 var converterAttr = objectType.GetCustomAttribute<JsonConverterAttribute>(); if (converterAttr != null && converterAttr.ConverterType == typeof(MySpecialConverter)) { // 从服务容器获取已注入服务的转换器实例 var converter = _serviceProvider.GetService(converterAttr.ConverterType) as JsonConverter; if (converter != null) { contract.Converter = converter; } } return contract; } }
2. 配置并使用
var resolver = new InjectableContractResolver(serviceProvider); var settings = new JsonSerializerSettings { ContractResolver = resolver }; var result = JsonConvert.DeserializeObject<IMyInterface>(jsonString, settings);
关键注意事项
- 确保服务和转换器已在DI容器中正确注册(例如ASP.NET Core中):
services.AddScoped<IMyService, MyServiceImpl>(); services.AddScoped<MySpecialConverter>(); - 若有多个自定义转换器,可扩展
InjectableContractResolver中的判断逻辑,批量处理不同转换器类型。
内容的提问来源于stack exchange,提问作者Jakub Vojtašák
相关产品推荐
相关产品推荐

