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

System.Text.Json序列化ILevel2时未包含ILevel1属性的原因及解决方法

System.Text.Json序列化接口继承属性丢失问题解决

问题原因

System.Text.Json默认只序列化编译时可见的类型成员。当你用ILevel2类型的变量调用序列化时,编译器仅能识别ILevel2自身定义的Scrore属性,不会自动遍历它继承自ILevel1的Name和City——接口的继承关系不会被序列化器自动解析。

解决方案

方案1:指定实际序列化类型

序列化时显式指定对象的实际类型(即FullClass),让序列化器知道要处理所有成员:

// 方式1:使用非泛型重载,传入实际类型
Console.WriteLine(JsonSerializer.Serialize(level2, typeof(FullClass)));

// 方式2:使用泛型重载,指定实际类型
Console.WriteLine(JsonSerializer.Serialize<FullClass>(level2));

方案2:用JsonDerivedType标记接口

在ILevel2接口上添加JsonDerivedType特性,告诉序列化器该接口的实际实现类型,这样序列化时会自动包含所有继承的属性:

[JsonDerivedType(typeof(FullClass))]
public interface ILevel2 : ILevel1
{
    int Scrore { get; set; }
}

之后直接序列化ILevel2变量就能得到预期结果:

Console.WriteLine(JsonSerializer.Serialize(level2)); 
// 输出:{"Scrore":10,"Name":"Benjamin","City":"Lille"}

方案3:自定义Json转换器(复杂场景)

如果有多个实现类型,或者需要更灵活的控制,可以自定义转换器遍历接口的所有属性:

public class InterfaceConverter<T> : JsonConverter<T> where T : class
{
    public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }

    public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
    {
        var jsonObj = new JsonObject();
        // 遍历所有接口的属性
        foreach (var prop in value.GetType().GetProperties())
        {
            jsonObj.Add(prop.Name, JsonSerializer.SerializeToElement(prop.GetValue(value), options));
        }
        jsonObj.WriteTo(writer);
    }
}

使用时在序列化选项中添加转换器:

var options = new JsonSerializerOptions();
options.Converters.Add(new InterfaceConverter<ILevel2>());
Console.WriteLine(JsonSerializer.Serialize(level2, options));

原问题代码示例

var obj = new FullClass() { Name = "Benjamin", Scrore = 10, City = "Lille"};

ILevel1 level1 = obj as ILevel1;
ILevel2 level2 = obj as ILevel2;

Console.WriteLine(JsonSerializer.Serialize(obj)); //==>  {"Scrore":10,"Name":"Benjamin","City":"Lille"}
Console.WriteLine(JsonSerializer.Serialize(level1)); //==> {"Name":"Benjamin","City":"Lille"}
Console.WriteLine(JsonSerializer.Serialize(level2)); //==> {"Scrore":10}

public interface ILevel1
{
    string Name { get; set; }
    string City { get; set; }
}

public interface ILevel2 : ILevel1
{
    int Scrore { get; set; }
}

public class FullClass : ILevel2
{
    public int Scrore { get; set; }
    public string Name { get; set; }
    public string City { get; set; }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 11:38:48