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

如何修复ASP.NET控制器无法返回子类数据的问题?

抽象类列表序列化丢失子类属性的解决方法

问题场景

我定义了抽象类MyAbsData,MyExtraData和MySpecialData两个类继承自它;容器类DataContainer包含该抽象类类型的列表。当通过API控制器返回容器时,列表里的子类MyExtraData专属字段Data2丢失,仅保留父类MyAbsData的Data1属性。

相关代码

控制器及实体类代码:

[ApiController]
[Route("container")]
public class TestingController : ControllerBase
{
    [HttpGet("")]
    public DataContainer GetContainer()
    {
        var container = new DataContainer();
        container.AddData(new MySpecialData(0));
        container.AddData(new MySpecialData(1));
        container.AddData(new MyExtraData(2, 3));
        container.AddData(new MyExtraData(4, 5));
        container.AddData(new MyExtraData(6, 7));
        container.AddData(new MySpecialData(8));

        return container;
    }
}

public class DataContainer
{
    public List<MyAbsData> MyList { get; }

    public DataContainer()
    {
        MyList = new List<MyAbsData>();
    }

    public void AddData(MyAbsData data)
    {
        MyList.Add(data);
    }
}

public abstract class MyAbsData
{
    public int Data1 { get; }

    public MyAbsData(int data1)
    {
        Data1 = data1;
    }
}

public class MySpecialData : MyAbsData
{
    public MySpecialData(int data1) : base(data1) { }
}

public class MyExtraData : MyAbsData
{
    public int Data2 { get; }

    public MyExtraData(int data1, int data2) : base(data1)
    {
        Data2 = data2;
    }
}

当前返回结果

{
"myList": [
{
"data1": 0
},
{
"data1": 1
},
{
"data1": 2
},
{
"data1": 4
},
{
"data1": 6
},
{
"data1": 8
}
]
}

期望返回结果包含MyExtraData的Data2字段。


解决方案

方法1:用[JsonDerivedType]特性标记抽象类(推荐)

在抽象类上显式声明所有子类,让System.Text.Json序列化器识别并保留子类属性:

[JsonDerivedType(typeof(MySpecialData))]
[JsonDerivedType(typeof(MyExtraData))]
public abstract class MyAbsData
{
    public int Data1 { get; }

    public MyAbsData(int data1)
    {
        Data1 = data1;
    }
}

修改后返回结果会自动包含Data2:

{
    "myList": [
        {
            "data1": 0
        },
        {
            "data1": 1
        },
        {
            "data1": 2,
            "data2": 3
        },
        {
            "data1": 4,
            "data2": 5
        },
        {
            "data1": 6,
            "data2": 7
        },
        {
            "data1": 8
        }
    ]
}

方法2:全局配置序列化器类型信息

如果不想修改实体类,可以在Program.cs中全局配置序列化选项,指定抽象类的子类:

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver
        {
            Modifiers =
            {
                typeInfo =>
                {
                    if (typeInfo.Type == typeof(MyAbsData))
                    {
                        typeInfo.PolymorphismOptions = new JsonPolymorphismOptions
                        {
                            DerivedTypes =
                            {
                                new JsonDerivedType(typeof(MySpecialData)),
                                new JsonDerivedType(typeof(MyExtraData))
                            }
                        };
                    }
                }
            }
        };
    });

方法3:切换为Newtonsoft.Json序列化

如果项目使用Newtonsoft.Json,可开启类型名称处理:

  1. 安装NuGet包Microsoft.AspNetCore.Mvc.NewtonsoftJson
  2. 在Program.cs中配置:
builder.Services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
    });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 16:05:16