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

.NET 4.7迁移至.NET 6.0时System.Text.Json多态序列化问题咨询

.NET 6 System.Text.Json 多态序列化最优解决方案

问题根因

System.Text.Json默认按接口/方法声明的返回类型做序列化,而非运行时实际返回的派生类类型,和Newtonsoft.Json默认按运行时类型序列化的行为不同,是导致该问题的核心原因。

方案1:已知派生类范围场景(推荐)

对于派生类可枚举的情况,直接在基类/接口上使用System.Text.Json原生的[JsonDerivedType]注解即可实现完整序列化派生类属性的需求:

using System.Text.Json.Serialization;

// 基类标注所有支持的派生类,不需要类型鉴别符可省略第二个参数
[JsonDerivedType(typeof(ConcreteProduct))]
[JsonDerivedType(typeof(VirtualProduct))]
public abstract class BaseProduct
{
    public long Id { get; set; }
    public string Name { get; set; }
}

public class ConcreteProduct : BaseProduct
{
    public decimal Weight { get; set; }
    public string DeliveryAddress { get; set; }
}

public class VirtualProduct : BaseProduct
{
    public string DownloadUrl { get; set; }
    public int ExpireDays { get; set; }
}

该方案无需修改全局配置,侵入性极低,符合.NET官方推荐的多态序列化实现方式。

方案2:未知派生类/全局多态场景

如果派生类无法提前枚举,或者需要全局适配所有多态返回值,可以自定义通用序列化转换器实现:

  1. 定义通用运行时类型序列化转换器
using System.Text.Json;
using System.Text.Json.Serialization;

public class RuntimeTypeJsonConverter<TBase> : JsonConverter<TBase>
{
    public override TBase? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // 反序列化逻辑按需实现,不需要可直接抛出异常
        return JsonSerializer.Deserialize<TBase>(ref reader, options);
    }

    public override void Write(Utf8JsonWriter writer, TBase value, JsonSerializerOptions options)
    {
        // 按运行时实际类型序列化,输出所有属性
        JsonSerializer.Serialize(writer, value, value.GetType(), options);
    }
}
  1. 全局注册转换器,在Program.cs中添加配置:
builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        // 按需为需要多态序列化的基类/接口添加转换器
        options.JsonSerializerOptions.Converters.Add(new RuntimeTypeJsonConverter<BaseProduct>());
        options.JsonSerializerOptions.Converters.Add(new RuntimeTypeJsonConverter<IBaseBusinessModel>());
    });

之前尝试的System.Runtime.Serialization相关注解未生效,是因为System.Text.Json默认不读取DataContract系列注解的多态配置,需要额外配置兼容开关,不如上述原生特性/转换器方案更直接。

轻量场景临时适配

如果仅个别接口有多态序列化需求,无需改全局配置,直接将接口返回值声明为object,或者手动按运行时类型序列化后返回即可。

后续版本升级提示

若后续升级到.NET 7及以上版本,可直接在基类上添加[JsonPolymorphic(UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToNearestAncestor)]特性,无需额外配置即可实现与Newtonsoft.Json完全一致的多态序列化行为,适配成本更低。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 17:45:08