c# - 如何将请求主体反序列化为子类?
问题描述
我们有一个由 OpenAPI 规范 (v3) 定义的 API。有一个 Cat 和 Dog 都继承自的 Animal 类。当生成的 C# 客户端发出请求时,例如对 a List<Animal>
,它们被正确地反序列化为子类。但是,如果我们尝试发布List<Animal>
包含 Cats 和 Dogs 的内容,生成的 C# ASP.NET 后端只会将它们作为 Animals 而不是子类获取。当我们使用 Postman 发布 Cat 时,后端会收到 Animal,所以我很确定这是 ASP.NET 生成问题。
spec.yaml 是:
openapi: 3.0.0
paths:
/saveData:
post:
description: Send all the data required
parameters:
- name: id
in: query
required: true
description: The id of the animal
schema:
type: string
format: uuid
example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SaveData'
responses:
200:
description: The animal
content:
application/json:
schema:
$ref: '#/components/schemas/Animal'
401:
$ref: '#/components/responses/Unauthorised'
400:
$ref: '#/components/responses/BadRequest'
components:
schemas:
SaveData:
type: object
required:
- animals
properties:
animals:
type: array
description: A list of animals
items:
$ref: '#/components/schemas/Animal'
Animal:
type: object
discriminator:
propertyName: className
required:
- "id"
- "name"
- "className"
properties:
id:
type: string
description: The unique ID of this object
format: uuid
example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
name:
type: string
description: Gives a name to the animal
example: Bob
className:
type: string
description: Determines which child class this object is
example: Cat
Cat:
allOf:
- $ref: '#/components/schemas/Animal'
Dog:
allOf:
- $ref: '#/components/schemas/Animal'
- type: object
required:
- "breed"
properties:
breed:
type: string
description: The breed of dog
example: Terrier
nullable: true
一个示例请求正文将是:
{
"animals": [
{
"id": "84d40807-4c68-4b41-9c24-619847e80269",
"name": "Bob",
"className": "Cat"
},
{
"id": "67a4b35e-4fc3-4a67-a77a-2a032640559f",
"name": "Spot",
"breed": "Husky",
"className": "Dog"
}
]
}
这些都被反序列化为 Animal,因此 Dog 失去了它的子属性。
我们如何调整定义或生成以允许这些类在服务器端正确反序列化?
解决方案
事实证明这是一个非常容易解决的问题。客户端代码生成包括JsonSubtypes
正确反序列化所需的属性。
在上面的示例中,Animal 类的开头应如下所示:
using JsonSubTypes;
[JsonConverter(typeof(JsonSubtypes), "className")]
[JsonSubtypes.KnownSubType(typeof(Cat), "Cat")]
[JsonSubtypes.KnownSubType(typeof(Dog), "Dog")]
public partial class Animal
{
// Class stuff here
}
我也不得不跑去dotnet add .\myproject.csproj package JsonSubTypes
拿包裹。
推荐阅读
- javascript - JWK“key_ops”成员与 Web Crypto 调用指定的成员不一致
- f# - 如何使用 F# 实现这个通用 C# 接口?
- javascript - innerHTML Web 组件中的 @import CSS 文件不起作用
- java - 请求超时 - JMeter HTTP2 插件
- sql - 让 Visual Studio SQL 只打印一次员工姓名
- python - 从多个文件夹中的多个 .xml 文件中提取数据
- android - 如何为 muc 添加图标/头像?
- haskell - 如何在 Haskell 中用守卫替换大小写或匹配模式?
- java - 如何在不使用 ImageView 的情况下从 API 端点下载图像或位图?
- angular - 如何让子组件知道输入发生了变化?