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

web,api,接口,返回,实现,集合,姿势,了解 · 浏览次数 : 240

小编点评

**问题** 接口返回值类型为`IEnumerable<PersonBase>`,但子类`Student`和`Employ`的扩展属性(`Student`的`Number`属性,`Employ`的`CompanyName`属性)未被序列化展示。 **解决方案** **2.1、.NET 7之前的实现方式** * 将接口返回值由`IEnumerable<PersonBase>`改为`object`。 * 接口实现的`List<PersonBase>`改为`List<object>`。 **2.2、.NET 7及以后的实现方式** * 支持使用特性标注的多态类型层次结构序列化和反序列化。 * 接口恢复,在抽象类上添加特性,标明基类序列化时需要映射的子类类型。 **总结** 使用 .NET 7 及以后的版本,接口返回值应使用特性标注的多态类型层次结构序列化和反序列化,以便子类属性 được序列化。

正文

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

一. 问题描述

如下图,定义两个子类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接口返回实现类集合的姿势了解

大家好,我是沙漠尽头的狼。 一. 问题描述 如下图,定义两个子类Student和Employ,都继承自抽象类PersonBase: public abstract class PersonBase { public string Name { get; set; } protected Person

利用云服务提供商的免费证书,在服务器上发布https前端应用和WebAPI的应用

我们如果要在服务器上发布https前端应用和WebAPI的应用,那么我们就需要用到https证书了。我们一般发布的应用的云服务器上,都会提供一定量的相关的免费证书(一般为20个)供我们使用,每个一年期限,到期再续即可,一般情况下基本上满足要求了,本篇随笔介绍如何基于云服务提供商的免费证书,在服务器上发布Nginx的前端应用和基于IIS的Web API接口的https应用处理。

再谈http请求调用(Post与Get),项目研发的核心一环

支持.Net Core(2.0及以上)与.Net Framework(4.0及以上) 【目录】 前言 Post请求 Get请求 与其它工具的比较 1【前言】 http请求调用是开发中经常会用到的功能。 在内,调用自有项目的Web Api等形式接口时会用到;在外,调用一些第三方功能接口时,也会用到,因

python flask 提供web的get/post开发

转载请注明出处: 使用python flask框架编写web api中的get与post接口,代码编写与调试示例如下: from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/api/get', met

Asp-Net-Core开发笔记:API版本管理

## 前言 对于Web API应用程序而言,随着时间的推移以及需求的增加或改变,API必然会遇到升级的需求。事实上,Web API应用程序应该从创建时就考虑到API版本的问题。业务的调整、功能的增加、接口的移除与改名、接口参数变动、实体属性的添加、删除和更改等都会改变API的功能,从而带来版本的变更

基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求

在前面随笔介绍的基于SqlSugar的WInform端管理系统中,数据提供者是直接访问数据库的方式,不过窗体界面调用数据接口获取数据的时候,我们传递的是标准的接口,因此可扩展性比较好。我曾经在随笔《基于SqlSugar的开发框架循序渐进介绍(5)-- 在服务层使用接口注入方式实现IOC控制反转》中介绍过,该SqlSugar开发框架本身是基于IOC控制反转的,因此对于接入不同的数据提供者,只需要切换

基于SqlSugar的开发框架循序渐进介绍(24)-- 使用Serialize.Linq对Lambda表达式进行序列化和反序列化

在上篇随笔《基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求》中介绍了基于一个接口,实现对两种不同接入方式(直接访问数据库实现,基于Web API代理类实现)的处理,由于定义的接口中,我们为了方便,也是用了Lambda表达式的进行一些参数的处理,那么如果在Web API代理类中,Lambda表达式是不能直接传递给Web API的控

Web 应用程序中进行多线程处理-Web Workers

1、什么是Web Workers? Web Workers API 是一组用于创建并在后台运行脚本的接口,以便在 Web 应用程序中进行多线程处理。它使得可以将一些耗时的计算任务放在单独的线程中执行,从而避免阻塞主线程,提高了应用程序的响应性能。 2、使用方式 以下是 Web Workers API

万物皆可集成系列:低代码对接Web Service接口

我们知道活字格支持不写代码实现双向API绑定,那么没那么主流的Web Service接口(SOAP协议+XML交互格式)呢?其实对接的思路没有那么复杂,得用C#编码来对接的。 作为一款企业级低代码开发平台,活字格可以和许多第三方软硬件进行集成,灵活、高效使它不可忽视的优势。在之前的内容中我们已经介绍

dubbo~全局异常拦截器的使用与设计缺陷

异常拦截器ExceptionMapper 在JAX-RS(Java API for RESTful Web Services)中,ExceptionMapper接口用于将Java异常映射到HTTP响应。通过实现ExceptionMapper接口,你可以自定义如何处理特定类型的异常,并生成相应的HTT