.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:未知派生类/全局多态场景
如果派生类无法提前枚举,或者需要全局适配所有多态返回值,可以自定义通用序列化转换器实现:
- 定义通用运行时类型序列化转换器
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); } }
- 全局注册转换器,在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
相关产品推荐
相关产品推荐

