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

System.Text.Json:如何反序列化含接口属性的类(.NET 6)

从Newtonsoft迁移到System.Text.Json:接口属性反序列化的简化方案

问题描述

我正在从Newtonsoft迁移至System.Text.Json,Newtonsoft可自动反序列化包含接口属性的对象,但使用System.Text.Json时会抛出如下错误:

each parameter in the deserialization constructor must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object.

编写自定义转换器能规避该问题,但面对多层嵌套的接口属性(每层接口属性又包含多个接口属性),需要编写大量转换器,开销太大。有没有更简便的解决方案?

示例代码

[Fact]
public void JsonTest()
{
    var child = new Child(new Name("Peter"), 10);
    var parent = new Parent(child);

    var str = JsonSerializer.Serialize(parent);
    var jsonObj = JsonSerializer.Deserialize<Parent>(str);
    Console.WriteLine(jsonObj!.Child.Name);
}

public class Parent
{
    public Parent(Child child)
    {
        Child = child;
    }

    public IChild Child { get; set;}
}

public class Child : IChild
{
    [JsonConstructor]
    public Child(Name name, int age)
    {
        Name = name;
        Age = age;
    }

    public IName Name { get; set; }
    public int Age { get; set; }
}

public class Name : IName
{
    public string NameValue { get; set; }
    public Name(string nameValue)
    {
        NameValue = nameValue;
    }
}

public interface IChild
{
    IName Name { get; }
    int Age { get; }
}

public interface IName
{
    string NameValue { get; }
}

简化解决方案

方案1:对齐构造函数参数与属性名

System.Text.Json的构造函数绑定要求参数名与属性名严格匹配(默认大小写敏感)。只需调整构造函数参数名,使其对应属性名一致,再配合大小写不敏感配置即可:

修改Parent类构造函数:

public class Parent
{
    // 参数名改为Child,与属性名一致
    public Parent(Child Child)
    {
        this.Child = Child;
    }

    public IChild Child { get; set;}
}

反序列化时启用大小写不敏感:

var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true
};
var jsonObj = JsonSerializer.Deserialize<Parent>(str, options);

方案2:通用接口转换器(批量处理接口-实现类映射)

编写一个泛型转换器,预先注册所有接口与对应实现类的映射,一次性处理所有嵌套场景,无需为每个类单独写转换器:

public class InterfaceConverter<TInterface, TImplementation> : JsonConverter<TInterface>
    where TImplementation : class, TInterface
{
    public override TInterface Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return JsonSerializer.Deserialize<TImplementation>(ref reader, options)!;
    }

    public override void Write(Utf8JsonWriter writer, TInterface value, JsonSerializerOptions options)
    {
        JsonSerializer.Serialize(writer, (TImplementation)value, options);
    }
}

使用时在配置中注册映射:

var options = new JsonSerializerOptions
{
    Converters =
    {
        new InterfaceConverter<IChild, Child>(),
        new InterfaceConverter<IName, Name>()
    }
};

// 序列化与反序列化均使用该配置
var str = JsonSerializer.Serialize(parent, options);
var jsonObj = JsonSerializer.Deserialize<Parent>(str, options);

方案3:为实现类添加无参数构造函数(适用于可变对象)

如果业务允许,给实现类添加无参数构造函数,同时确保属性可写,System.Text.Json会自动完成反序列化:

public class Name : IName
{
    public string NameValue { get; set; }
    
    // 添加无参数构造函数
    public Name() {}
    
    public Name(string nameValue)
    {
        NameValue = nameValue;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 06:32:04