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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 09:10:28