.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
相关产品推荐
相关产品推荐

