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

如何通过自定义IJsonTypeInfoResolver拦截System.Text.Json反序列化的Person实例?

如何通过自定义JsonTypeInfoResolver拦截反序列化的Person实例

可以通过继承DefaultJsonTypeInfoResolver并修改Person类型对应的JsonTypeInfo配置来实现拦截需求。核心思路是针对Person类型,替换其对象创建逻辑或者添加反序列化完成后的回调,从而在实例创建/初始化完成后拿到对象进行处理。

实现方案1:拦截刚创建的未赋值实例

通过替换JsonTypeInfo.CreateObject方法,在Person实例刚创建时立即拦截(此时属性尚未赋值):

var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true,
    TypeInfoResolver = new JsonCustomResolver()
};

options.Converters.Add(new JsonDateTimeConverter());
options.Converters.Add(new JsonDateOnlyConverter());
options.Converters.Add(new JsonColorConverter());
options.Converters.Add(new JsonDecimalConverter());

var people = await JsonSerializer.DeserializeAsync<List<Person>>(stream, options);

sealed record Person
{
    public string FullName { get; set; }
    public int Age { get; set; }
}

sealed class JsonCustomResolver : DefaultJsonTypeInfoResolver
{
    public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
    {
        var info = base.GetTypeInfo(type, options);

        // 仅对Person类型应用拦截逻辑
        if (type == typeof(Person))
        {
            var originalCreate = info.CreateObject;
            
            // 替换原有实例创建逻辑
            info.CreateObject = () =>
            {
                var person = (Person)originalCreate();
                // 此处拿到刚创建的Person实例,属性尚未赋值
                Console.WriteLine($"拦截到新创建的Person实例");
                return person;
            };
        }

        return info;
    }
}

实现方案2:拦截已完成赋值的实例

如果需要在Person所有属性都完成反序列化赋值后再拦截,可使用JsonTypeInfo.OnDeserialized回调:

sealed class JsonCustomResolver : DefaultJsonTypeInfoResolver
{
    public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
    {
        var info = base.GetTypeInfo(type, options);

        if (type == typeof(Person))
        {
            // 初始化回调列表(避免空引用)
            info.OnDeserialized ??= new List<Action<object, JsonSerializerContext>>();
            // 添加反序列化完成后的处理逻辑
            info.OnDeserialized.Add((obj, context) =>
            {
                var person = (Person)obj;
                // 此时Person的所有属性已完成赋值
                Console.WriteLine($"拦截到已赋值的Person:{person.FullName},年龄{person.Age}");
                // 可在此修改实例属性或执行其他业务逻辑
            });
        }

        return info;
    }
}

关键说明

  • 两种方案的核心差异:CreateObject拦截的是刚创建但未赋值的实例,OnDeserialized拦截的是已完成所有属性填充的实例,可根据实际需求选择。
  • 无需额外处理List<Person>类型,因为反序列化列表时,内部会逐个创建Person实例,只要针对Person类型配置拦截逻辑,每个实例都会触发对应处理。

内容的提问来源于stack exchange,提问作者iam3yal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 21:40:20