如何修复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,可开启类型名称处理:
- 安装NuGet包
Microsoft.AspNetCore.Mvc.NewtonsoftJson - 在
Program.cs中配置:
builder.Services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto; });
内容的提问来源于stack exchange,提问作者bogo_sorter
相关产品推荐
相关产品推荐

