こんにちは、私は砂漠の果ての狼です。
I.はじめに問題の説明
次の図では、抽象クラスPersonBaseから継承する2つのサブクラスStudentとEmployを定義します。
public abstract class PersonBase
{
public string Name { get; set; }
protected PersonBase(string name)
{
Name = name;
}
}
public class Student : PersonBase
{
public string Number { get; set; }
public Student(string name, string number) : base(name)
{
Number = number;
}
}
public class Employ : PersonBase
{
public string CompanyName { get; set; }
public Employ(string name, string companyName) : base(name)
{
CompanyName = companyName;
}
}
Web APIインタフェースを追加してベースクラスコレクションを返す
[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
[HttpGet(Name = "GetDetails")]
public IEnumerable<PersonBase> Get()
{
return new List<PersonBase>()
{
new Student("学生A", "学生号01"),
new Employ("职员01", "百度")
};
}
}
インターフェイスの戻り値
[
{
"name": "学生A"
},
{
"name": "职员01"
}
]
問題は見つかった?StudentクラスとEmployクラスインスタンスの拡張プロパティ(StudentのNumberプロパティ、EmployのCompanyプロパティ)がシリアライズされていない場合、サブクラスのすべてのプロパティをシリアライズする方法は?
2.クラスの全プロパティのシリアル化の実装
参考微软文档《如何使用System.Text.Json序列化派生类的属性》,有两种实现方式站长觉得比较简单。
2.1. NET 7以前の実装方法
NET 7より前のバージョンでは、System. Text.Jsonはポリモーフィック型階層のシリアライズをサポートしていませんでした。例えば、インターフェイスの戻り値型がインターフェイスまたは抽象クラスのコレクションである場合、ランタイム型に他のプロパティがあっても、インターフェイスまたは抽象クラス定義のプロパティのみがシリアル化されます。
解决方案:将接口返回值由IEnumerable<PersonBase>改为object,接口实现的List<PersonBase>改为List<object>:
[HttpGet(Name = "GetDetails")]
public object Get()
{
return new List<object>()
{
new Student("学生A", "学生号01"),
new Employ("职员01", "百度")
};
}
変更後、インターフェイスは詳細なJSON情報を正常に返しました。
[
{
"number": "学生号01",
"name": "学生A"
},
{
"companyName": "百度",
"name": "职员01"
}
]
原理: Objectに変更した後、デフォルトでは実装クラスがシリアル化され、System.Text.Jsonは実装クラスの父親しか知らない。
2.2. NET 7以降の実装。
NET 7以降、System. Text.Jsonは機能注釈を使用した多相型階層のシリアライズとデシリアライズをサポートしている。
インターフェイスを復元し、抽象クラスに機能を追加して、ベースクラスのシリアル化時にマッピングする必要があるサブクラスの型を指定します。
[JsonDerivedType(typeof(Student))]
[JsonDerivedType(typeof(Employ))]
public abstract class PersonBase
問題解決、インターフェイスの戻り値は同じです。
文档关于JsonDerivedTypeAttribute的描述:当放置在类型声明中时,则指示应选择指定的子类型进行多态序列化。 它还公开用于指定类型鉴别器的功能。
III.サマリー
上面两种方式看.NET版本选择,第二种方式需要您明确知道子类类型,详细使用请看微软文档:如何使用System.Text.Json序列化派生类的属性
より良い方法があれば、メッセージを歓迎します。
- 微信技術交流グループ:微信(codewf)コメント“グループに入る”を追加
- QQ技術交流グループ:77 199230 0。
