C#序列化未完整输出派生类属性问题求助
C# System.Text.Json 序列化派生类属性丢失问题解决
问题背景
定义抽象基类Person,派生类Student(包含独有属性AvgGrade)、Professor(包含独有属性Salary)。当序列化List<Person>集合时,仅能输出基类的OIB、Name、Date、Gender属性,派生类的独有属性未被序列化。
相关代码片段
序列化服务类
using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Text.Json; namespace TxtToXmlParser.Parser { public static class JSONserializerService { public static void Serialize<T>(string filePath,T data) { var jsonString = JsonSerializer.Serialize(data); using FileStream fs = File.OpenWrite(filePath); byte[] bytes = Encoding.UTF8.GetBytes(jsonString); fs.Write(bytes, 0, bytes.Length); } } }
Person基类
public abstract class Person { public string OIB { get; set; } public string Name { get; set; } public DateTime Date{ get; set; } public Gender Gender{ get; set; } public Person() { } protected Person(string oIB, string name, Gender gender, DateTime date) { OIB = oIB; Name = name; Date = date; Gender = gender; } }
Student派生类
public class Student : Person { public float AvgGrade { get; set; } public Student() { } public Student(float avgGrade, string oIB, string name, Gender gender, DateTime date) : base(oIB, name, gender, date) { AvgGrade = avgGrade; } }
实际与期望输出
- 实际序列化结果(仅基类属性):
[{"OIB":"001212","Name":"Iva Ivić","Date":"1998-02-02T00:00:00","Gender":1},{"OIB":"001213","Name":"Ivan Zoraja","Date":"1961-01-01T00:00:00","Gender":0}]
- 期望序列化结果(包含派生类属性):
[{"OIB":"001212","Name":"Iva Ivić","Date":"1998-02-02T00:00:00","Gender":1,"Grade":"4.3"},{"OIB":"001213","Name":"Ivan Zoraja","Date":"1961-01-01T00:00:00","Gender":0,"Salary":"10020.00"}]
解决方案
System.Text.Json默认不支持隐式多态序列化,需显式配置派生类的类型信息,以下提供两种实现方式:
方式一:通过特性标记基类(推荐,代码更直观)
在抽象基类Person上添加多态序列化特性,指定所有派生类型:
using System.Text.Json.Serialization; [JsonPolymorphic(TypeDiscriminatorPropertyName = "$type")] [JsonDerivedType(typeof(Student), typeDiscriminator: "Student")] [JsonDerivedType(typeof(Professor), typeDiscriminator: "Professor")] public abstract class Person { // 原有属性及构造函数... }
修改后直接使用原序列化方法即可,序列化结果会自动包含派生类属性,同时添加类型鉴别符$type(用于反序列化时识别类型)。
方式二:通过JsonSerializerOptions配置(灵活,无需修改基类)
修改序列化方法,在JsonSerializer.Serialize时传入配置好的JsonSerializerOptions,显式指定基类的派生类型:
public static void Serialize<T>(string filePath, T data) { var options = new JsonSerializerOptions { // 可选:格式化JSON输出,便于阅读 WriteIndented = true, TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => { if (typeInfo.Type == typeof(Person)) { typeInfo.PolymorphismOptions = new JsonPolymorphismOptions { DerivedTypes = { new JsonDerivedType(typeof(Student), "Student"), new JsonDerivedType(typeof(Professor), "Professor") } }; } } } } }; var jsonString = JsonSerializer.Serialize(data, options); using FileStream fs = File.OpenWrite(filePath); byte[] bytes = Encoding.UTF8.GetBytes(jsonString); fs.Write(bytes, 0, bytes.Length); }
效果验证
修改后序列化的JSON示例(含派生类属性):
[ { "$type": "Student", "AvgGrade": 4.3, "OIB": "001212", "Name": "Iva Ivić", "Date": "1998-02-02T00:00:00", "Gender": 1 }, { "$type": "Professor", "Salary": 10020.0, "OIB": "001213", "Name": "Ivan Zoraja", "Date": "1961-01-01T00:00:00", "Gender": 0 } ]
注:类型鉴别符
$type是反序列化时识别派生类型的必要标识,若仅需序列化无需反序列化,可通过配置JsonPolymorphismOptions.IgnoreUnrecognizedTypeDiscriminators = true并自定义鉴别符,但不建议省略,避免后续反序列化出现问题。
内容的提问来源于stack exchange,提问作者user19460705
相关产品推荐
相关产品推荐

