问题描述
我们有一个由OpenAPI规范(v3)定义的API。有一个动物类,猫和狗都继承自。当生成的C#客户端发出请求时,例如说List<Animal>
,它们将正确反序列化为子类。但是,如果我们尝试发布包含猫和狗的List<Animal>
,则生成的C#ASP.NET后端只会将它们作为动物而不是子类来获取。当我们使用邮递员发布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
来获取软件包。