大家好,我是沙漠盡頭的狼。 一. 問題描述 如下圖,定義兩個子類Student和Employ,都繼承自抽象類PersonBase: public abstract class PersonBase { public string Name { get; set; } protected Person ...
大家好,我是沙漠盡頭的狼。
一. 問題描述
如下圖,定義兩個子類Student和Employ,都繼承自抽象類PersonBase:
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屬性)都未被序列化展示,那麼怎麼序列化子類的所有屬性呢?
二、實現類的所有屬性序列化
參考微軟文檔《如何使用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
的描述:當放置在類型聲明中時,則指示應選擇指定的子類型進行多態序列化。 它還公開用於指定類型鑒別器的功能。
三、總結
上面兩種方式看.NET版本選擇,第二種方式需要您明確知道子類類型,詳細使用請看微軟文檔:如何使用System.Text.Json序列化派生類的屬性
如果您有更好的方式歡迎留言探討。
時間如流水,只能流去不流回。