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

.NET8中使用JsonDerivedType序列化泛型时缺失$type的问题

问题:.NET 8中泛型派生类序列化时$type字段缺失,JsonDerivedType特性未生效

在.NET 8框架下编写了如下代码,尝试用JsonDerivedType特性配置类型鉴别符,但序列化泛型派生类时,$type字段未生成,仅基类序列化时正常输出该字段。

代码实现

public partial class MainWindow : Window
{        
    public MainWindow()
    {
        InitializeComponent();
        Debug.WriteLine(JsonSerializer.Serialize<TestModel>(new TestModel() { Name = "123", Time = DateTime.Now }));
        Debug.WriteLine(JsonSerializer.Serialize<TestModelWithGeneric<int>>(new TestModelWithGeneric<int>() { Name = "123", Time = DateTime.Now ,Value=1}));
        Debug.WriteLine(JsonSerializer.Serialize<TestModelWithGeneric<string>>(new TestModelWithGeneric<string>() { Name = "123", Time = DateTime.Now, Value = "123" }));
    }
    [JsonDerivedType(typeof(TestModel), typeDiscriminator: "Base")]
    [JsonDerivedType(typeof(TestModelWithGeneric<int>), typeDiscriminator: "TestModelWithInt")]
    [JsonDerivedType(typeof(TestModelWithGeneric<string>), typeDiscriminator: "TestModelWithString")]
    public class TestModel {
        public string Name{ get; set; }
        public DateTime Time { get; set; }
    }
    public class TestModelWithGeneric<T> :TestModel{ 
        public T Value { get; set; }
    }
}   

序列化输出结果

{"$type":"Base","Name":"123","Time":"2023-12-04T15:29:49.7867248+08:00"}
{"Value":1,"Name":"123","Time":"2023-12-04T15:29:49.8314012+08:00"}
{"Value":"123","Name":"123","Time":"2023-12-04T15:29:49.8354174+08:00"}

解答

问题根源

JsonDerivedType特性的作用场景是:**当你序列化的是基类类型的变量(但实际指向派生类实例)**时,序列化器才会自动写入类型鉴别符$type,用于反序列化时识别具体的派生类型。

你当前序列化泛型派生类时,直接指定了具体的泛型类型(TestModelWithGeneric<int>/TestModelWithGeneric<string>)作为序列化的泛型参数,序列化器会认为你明确知道要序列化的具体类型,不需要额外写入类型鉴别符,因此JsonDerivedType特性不会生效。

解决方法

方法一:序列化时指定基类作为泛型参数

将泛型派生类的序列化代码改为以基类TestModel作为泛型参数,这样序列化器会识别到实际对象是派生类实例,自动写入$type字段:

// 修改后的序列化代码
Debug.WriteLine(JsonSerializer.Serialize<TestModel>(new TestModel() { Name = "123", Time = DateTime.Now }));
Debug.WriteLine(JsonSerializer.Serialize<TestModel>(new TestModelWithGeneric<int>() { Name = "123", Time = DateTime.Now ,Value=1}));
Debug.WriteLine(JsonSerializer.Serialize<TestModel>(new TestModelWithGeneric<string>() { Name = "123", Time = DateTime.Now, Value = "123" }));

修改后输出会包含对应的$type字段:

{"$type":"Base","Name":"123","Time":"2023-12-04T15:29:49.7867248+08:00"}
{"$type":"TestModelWithInt","Value":1,"Name":"123","Time":"2023-12-04T15:29:49.8314012+08:00"}
{"$type":"TestModelWithString","Value":"123","Name":"123","Time":"2023-12-04T15:29:49.8354174+08:00"}

方法二:强制配置序列化器输出类型鉴别符(不推荐)

如果业务场景必须直接序列化具体泛型类型同时保留$type,可以通过自定义JsonTypeInfo来强制添加类型鉴别符,但这种方式不符合类型鉴别符的设计初衷(类型鉴别符主要用于基类反序列化场景),不建议常规使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 21:53:29