ASP.NET Core Web API返回继承类实例列表时序列化丢失属性的解决方法
解决ASP.NET Core Web API返回多态对象数组时丢失子类属性的问题
这个问题太常见了——默认的JSON序列化器(现在ASP.NET Core原生用的是System.Text.Json)不会自动处理多态类型的序列化逻辑,所以当你返回List<MainClass>时,它只会序列化基类MainClass的属性,ClassA和ClassB的专属字段直接被忽略了。下面给你两种实用的解决方案:
方案1:用原生System.Text.Json开启多态支持
方式A:给基类加特性标记
直接在你的基类MainClass上添加[JsonDerivedType]特性,明确告诉序列化器要处理哪些派生类:
using System.Text.Json.Serialization; // 标记派生类,第二个参数是类型判别符(序列化时会自动添加这个字段区分类型) [JsonDerivedType(typeof(ClassA), typeDiscriminator: "class_a")] [JsonDerivedType(typeof(ClassB), typeDiscriminator: "class_b")] public class MainClass { public int Id { get; set; } public string BaseCommonProperty { get; set; } } public class ClassA : MainClass { public string ExclusivePropertyForA { get; set; } } public class ClassB : MainClass { public int ExclusivePropertyForB { get; set; } }
这样配置后,当你在控制器返回List<MainClass>时,序列化器会自动包含子类的专属属性,同时会带上你指定的类型判别字段,方便前端或者消费方区分不同类型。
方式B:全局配置派生类型
如果不想修改实体类的代码,可以在Program.cs的服务配置里全局设置:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers() .AddJsonOptions(options => { // 给MainClass添加派生类型支持 options.JsonSerializerOptions.TypeInfoResolverChain.Add( JsonSerializerOptions.Default.GetTypeInfo(typeof(MainClass)) .WithDerivedTypes(typeof(ClassA), typeof(ClassB)) ); });
这种方式更适合不能修改实体类源码的场景。
方案2:切换到Newtonsoft.Json(Json.NET)
如果你习惯用Json.NET,或者需要更灵活的多态处理逻辑,可以切换到它:
- 先安装NuGet包:
Microsoft.AspNetCore.Mvc.NewtonsoftJson - 在Program.cs中配置服务:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers() .AddNewtonsoftJson(options => { // 自动处理多态类型,序列化时会添加$type字段标记具体类型 options.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto; });
配置完成后,返回List<MainClass>时,Json.NET会自动序列化所有子类的专属属性,不需要额外给基类加标记。
验证示例(控制器代码)
最后给你一个控制器的示例,测试下效果:
[ApiController] [Route("api/polymorphic")] public class PolymorphicController : ControllerBase { [HttpGet] public ActionResult<List<MainClass>> GetItems() { var items = new List<MainClass> { new ClassA { Id = 1, BaseCommonProperty = "来自A的基础属性", ExclusivePropertyForA = "只有A才有的字符串" }, new ClassB { Id = 2, BaseCommonProperty = "来自B的基础属性", ExclusivePropertyForB = 12345 } }; return Ok(items); } }
现在调用这个接口,就能得到包含所有子类专属属性的JSON响应了。
内容的提问来源于stack exchange,提问作者Szymon D
相关产品推荐
相关产品推荐

