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

Posted Dotnet9个人博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Web API接口返回实现类集合的姿势了解相关的知识,希望对你有一定的参考价值。

大家好,我是沙漠尽头的狼。

一. 问题描述

如下图,定义两个子类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序列化派生类的属性

如果您有更好的方式欢迎留言探讨。

以上是关于Web API接口返回实现类集合的姿势了解的主要内容,如果未能解决你的问题,请参考以下文章

web前端怎么调用api接口

Java集合框架 List接口实现类--Vector的使用(了解即可)

第九章 集合

用ThreadLocal类实现线程安全的正确姿势

接口设计模式内部类的初步了解

JAVA基础--JAVA API集合框架(其他集合类,集合原理)15