翼度科技»论坛 编程开发 .net 查看内容

Web API接口返回实现类集合的姿势了解

10

主题

10

帖子

30

积分

新手上路

Rank: 1

积分
30
大家好,我是沙漠尽头的狼。
一. 问题描述

如下图,定义两个子类Student和Employ,都继承自抽象类PersonBase:
  1. public abstract class PersonBase
  2. {
  3.     public string Name { get; set; }
  4.     protected PersonBase(string name)
  5.     {
  6.         Name = name;
  7.     }
  8. }
  9. public class Student : PersonBase
  10. {
  11.     public string Number { get; set; }
  12.     public Student(string name, string number) : base(name)
  13.     {
  14.         Number = number;
  15.     }
  16. }
  17. public class Employ : PersonBase
  18. {
  19.     public string CompanyName { get; set; }
  20.     public Employ(string name, string companyName) : base(name)
  21.     {
  22.         CompanyName = companyName;
  23.     }
  24. }
复制代码
添加Web API接口返回基类集合:
  1. [ApiController]
  2. [Route("[controller]")]
  3. public class TestController : ControllerBase
  4. {
  5.     [HttpGet(Name = "GetDetails")]
  6.     public IEnumerable<PersonBase> Get()
  7.     {
  8.         return new List<PersonBase>()
  9.         {
  10.             new Student("学生A", "学生号01"),
  11.             new Employ("职员01", "百度")
  12.         };
  13.     }
  14. }
复制代码
接口返回值:
  1. [
  2.   {
  3.     "name": "学生A"
  4.   },
  5.   {
  6.     "name": "职员01"
  7.   }
  8. ]
复制代码
发现问题了吗?Student类和Employ类实例的扩展属性(Student的Number属性,Employ的Company属性)都未被序列化展示,那么怎么序列化子类的所有属性呢?
二、实现类的所有属性序列化

参考微软文档《如何使用System.Text.Json序列化派生类的属性》,有两种实现方式站长觉得比较简单。
2.1、.NET 7之前的实现方式

在 .NET 7 之前的版本中,System.Text.Json 不支持多态类型层次结构的序列化。 例如,如果接口的返回值类型为接口或抽象类集合,那么即使运行时类型具有其他属性,也只会序列化对接口或抽象类定义的属性。
解决方案:将接口返回值由IEnumerable改为object,接口实现的List改为List:
  1. [HttpGet(Name = "GetDetails")]
  2. public object Get()
  3. {
  4.     return new List<object>()
  5.     {
  6.         new Student("学生A", "学生号01"),
  7.         new Employ("职员01", "百度")
  8.     };
  9. }
复制代码
修改后,接口成功返回详细JSON信息:
  1. [
  2.   {
  3.     "number": "学生号01",
  4.     "name": "学生A"
  5.   },
  6.   {
  7.     "companyName": "百度",
  8.     "name": "职员01"
  9.   }
  10. ]
复制代码
原理: 改为Object后,默认就是对实现类进行序列化了,改之前System.Text.Json只认识实现类的爸爸。
2.2、.NET 7及以后的实现方式

从 .NET 7 开始,System.Text.Json 支持使用特性标注的多态类型层次结构序列化和反序列化。
我们将接口恢复,在抽象类上添加特性,标明基类序列化时需要映射的子类类型:
  1. [JsonDerivedType(typeof(Student))]
  2. [JsonDerivedType(typeof(Employ))]
  3. public abstract class PersonBase
复制代码
问题解决,接口返回值同上。
文档关于JsonDerivedTypeAttribute的描述:当放置在类型声明中时,则指示应选择指定的子类型进行多态序列化。 它还公开用于指定类型鉴别器的功能。
三、总结

上面两种方式看.NET版本选择,第二种方式需要您明确知道子类类型,详细使用请看微软文档:如何使用System.Text.Json序列化派生类的属性
如果您有更好的方式欢迎留言探讨。

来源:https://www.cnblogs.com/Dotnet9-com/archive/2023/03/19/17234396.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具