C#如何序列化基类列表中派生类的全部属性?
问题:序列化基类列表时保留派生类的Value属性
我需要用JsonSerializer.Serialize(...)序列化一个包含基类列表的类,但目前只有基类的属性被序列化,派生类的Value属性没有被输出。相关代码及当前问题如下:
模型定义
// ----- Models ----- public class MainClass { [Key] public Guid Id { get; private set; } = Guid.NewGuid(); public List<BaseClass> Properties { get; set; } = new List<BaseClass>(); } public class BaseClass { [Key] public Guid Id { get; private set; } = Guid.NewGuid(); public string Name { get; set; } = string.Empty; } public class GenericDerivedClass<T> : BaseClass { public T? Value { get; set; } }
实现代码
// ----- Implementation ----- var main = new MainClass { Properties = new List<BaseClass> { new GenericDerivedClass<string> { Name = "SoundFile", Value = "Test.wav" }, new GenericDerivedClass<float> { Name = "Volume", Value = 1 }, new GenericDerivedClass<bool> { Name = "Autoplay", Value = false }, new GenericDerivedClass<bool> { Name = "Loop", Value = false }, } }; Console.WriteLine(JsonSerializer.Serialize(main, new JsonSerializerOptions { WriteIndented = true }));
当前输出(缺失Value属性)
{ "Id": "ba348c86-aa86-45ea-8d21-a9beddd4368a", "Properties": [ { "Id": "a9f432d5-3916-4c1d-b44a-fd4b7d8fcb45", "Name": "SoundFile" // "value": "Test.wav" <- 需要保留这个属性 }, { "Id": "f585d863-b0d7-49b3-ad5c-0565171e6793", "Name": "Volume" }, { "Id": "197802f3-17cd-4c1f-90be-7ea643ee5d7d", "Name": "Autoplay" }, { "Id": "b90e3857-e497-4137-adeb-94b66293d375", "Name": "Loop" } ] }
需求:序列化MainClass时,让List<BaseClass>中的每个GenericDerivedClass<T>实例都输出Value属性,且不能用List<object>替代List<BaseClass>。
解决方案
方法1:使用JsonDerivedType特性(.NET 7+ 推荐)
在基类BaseClass上添加JsonDerivedType特性,指定所有需要被序列化的派生泛型具体类型:
[JsonDerivedType(typeof(GenericDerivedClass<string>), typeDiscriminator: "StringProperty")] [JsonDerivedType(typeof(GenericDerivedClass<float>), typeDiscriminator: "FloatProperty")] [JsonDerivedType(typeof(GenericDerivedClass<bool>), typeDiscriminator: "BoolProperty")] public class BaseClass { [Key] public Guid Id { get; private set; } = Guid.NewGuid(); public string Name { get; set; } = string.Empty; }
此时序列化会自动输出派生类的Value属性,同时默认添加类型鉴别符(如"$type": "StringProperty")。如果不需要类型鉴别符,可通过配置移除:
var options = new JsonSerializerOptions { WriteIndented = true, TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => { if (typeInfo.Type == typeof(BaseClass)) { typeInfo.PolymorphismOptions = null; } } } } }; Console.WriteLine(JsonSerializer.Serialize(main, options));
方法2:自定义Json转换器(兼容.NET 6及以下)
如果使用旧版本.NET,可自定义转换器强制序列化实际派生类型的所有属性:
public class BaseClassConverter : JsonConverter<BaseClass> { public override BaseClass? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 若需要反序列化,可补充对应逻辑 throw new NotImplementedException(); } public override void Write(Utf8JsonWriter writer, BaseClass value, JsonSerializerOptions options) { // 将基类实例转为object,让序列化器识别实际派生类型 JsonSerializer.Serialize(writer, (object)value, options); } }
序列化时添加该转换器即可:
var options = new JsonSerializerOptions { WriteIndented = true, Converters = { new BaseClassConverter() } }; Console.WriteLine(JsonSerializer.Serialize(main, options));
内容的提问来源于stack exchange,提问作者KarlSupertramp
相关产品推荐
相关产品推荐

