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

C#中含接口类型属性的对象反序列化问题

解决Json反序列化时接口类型属性绑定具体实现类的问题

问题场景

现有接口ISquare、ISide及其实现类Square、Side,其中Square类的属性Side为ISide类型,但构造函数接收的是具体Side类型参数。使用自定义ConcreteTypeConverter进行Json反序列化时,调用API传入指定JSON后触发错误:

System.InvalidOperationException: 'Each parameter in the deserialization constructor on type 'ProvaModel.Square' must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object. Fields are only considered when 'JsonSerializerOptions.IncludeFields' is enabled. The match can be case-insensitive.'

核心矛盾:需要保留属性的接口类型,但反序列化时无法自动将接口类型映射到具体实现类,导致构造函数参数绑定失败。

解决方案

方法1:修改构造函数参数类型为接口类型

直接将Square的构造函数参数类型从Side改为ISide,利用已标记在ISide上的JsonConverter特性自动完成具体类的反序列化:

internal class Square : ISquare
{
    public ISide Side { get; }

    [JsonConstructor]
    internal Square(ISide side) // 将参数类型改为ISide
    {
        Side = side;
    }
}

原理:ISide接口已标记[JsonConverter(typeof(ConcreteTypeConverter<Side>))],反序列化时JsonSerializer会自动将JSON中的side节点转换为Side实例,传给构造函数的ISide参数。此时参数名side与属性名Side(大小写不敏感)匹配,满足绑定要求,错误即可消除。

方法2:全局配置接口与具体类的映射

如果无法修改构造函数,可以在Json序列化配置中直接指定接口对应的具体实现类,无需依赖接口上的特性标记:

在Program.cs/Startup.cs的控制器配置中添加:

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        // 为ISide指定具体实现类Side
        options.JsonSerializerOptions.Converters.Add(new JsonConverter<ISide>()
        {
            public override ISide? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
            {
                return JsonSerializer.Deserialize<Side>(ref reader, options);
            }

            public override void Write(Utf8JsonWriter writer, ISide value, JsonSerializerOptions options)
            {
                JsonSerializer.Serialize(writer, value as Side, options);
            }
        });

        // 为ISquare指定具体实现类Square
        options.JsonSerializerOptions.Converters.Add(new JsonConverter<ISquare>()
        {
            public override ISquare? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
            {
                return JsonSerializer.Deserialize<Square>(ref reader, options);
            }

            public override void Write(Utf8JsonWriter writer, ISquare value, JsonSerializerOptions options)
            {
                JsonSerializer.Serialize(writer, value as Square, options);
            }
        });
    });

这种方式更灵活,适合无法修改原有类结构的场景。

错误原因说明

原错误的本质是:Square构造函数要求传入Side类型参数,但反序列化时,根据ISquare的Side属性类型(ISide),JsonSerializer会尝试生成ISide实例,无法直接转换为构造函数需要的Side类型,同时参数与属性的类型不匹配导致绑定失败。通过让构造函数接收接口类型,或全局配置接口到具体类的映射,即可解决类型不兼容的问题。

内容的提问来源于stack exchange,提问作者Manuel Venè

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 01:27:11