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

.NET 6.0 WebAPI多态列表返回缺失派生类属性问题咨询

序列化行为差异原因

.NET 6 内置的WebAPI默认使用System.Text.Json作为JSON序列化器,两个接口返回结果不一致是该序列化器的默认规则导致的:

  • 单个Client查询接口中,返回的client对象是序列化流程的根级值,序列化器会直接读取对象的运行时实际类型(比如TypeAClient),忽略Action签名上声明的Client基类类型,因此会序列化实际类型包含的所有属性(基类属性+派生类独有属性)。
  • 客户端列表查询接口中,返回的根级值是IEnumerable<Client>类型的集合,序列化集合内的元素时,会默认使用集合定义的元素声明类型(即基类Client)作为序列化依据,不会自动递归检查每个元素的运行时派生类型,因此只会输出基类中定义的属性,丢失派生类独有字段。
解决方案

最简便且性能最优的方案是使用.NET 6+原生提供的多态序列化配置,有两种实现方式:

方式1:在基类上标记多态派生类型(推荐)

直接给Client基类添加JsonDerivedType特性,声明所有可能出现的派生类型即可,不需要额外修改控制器代码,全局生效:

using System.Text.Json.Serialization;

// 声明所有继承自Client的派生类型
[JsonDerivedType(typeof(TypeAClient))]
[JsonDerivedType(typeof(TypeBClient))]
[JsonDerivedType(typeof(TypeCClient))]
public class Client
{
    // 基类原有属性定义
}

如果后续需要接口支持接收这些派生类型作为入参(反序列化多态类型),可以给每个派生类型指定唯一的类型鉴别器,序列化时会自动在JSON中增加类型标识字段供反序列化识别:

[JsonDerivedType(typeof(TypeAClient), "typeA")]
[JsonDerivedType(typeof(TypeBClient), "typeB")]
[JsonDerivedType(typeof(TypeCClient), "typeC")]

方式2:全局配置Json选项(无需修改实体类)

如果不想改动实体类定义,可以在Program.cs中配置控制器的JSON序列化选项,统一注册Client类的多态派生类型:

var builder = WebApplication.CreateBuilder(args);

// 注册控制器时配置Json选项
builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        var resolver = options.JsonSerializerOptions.TypeInfoResolver as DefaultJsonTypeInfoResolver;
        resolver.Modifiers.Add(typeInfo =>
        {
            // 仅针对Client类型配置多态
            if (typeInfo.Type == typeof(Client))
            {
                typeInfo.PolymorphismOptions = new JsonPolymorphismOptions
                {
                    DerivedTypes =
                    {
                        new JsonDerivedType(typeof(TypeAClient)),
                        new JsonDerivedType(typeof(TypeBClient)),
                        new JsonDerivedType(typeof(TypeCClient))
                    }
                };
            }
        });
    });

// 其余中间件配置保持不变

配置完成后重启服务,列表接口就会自动识别每个集合元素的实际派生类型,输出包含派生类独有属性的完整结果。

注:如果你的项目手动替换成了Newtonsoft.Json作为序列化器,需要额外配置TypeNameHandling参数实现派生类型属性序列化,逻辑与上述System.Text.Json的配置不同。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 23:51:28