You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 21:17:17