我正在使用Autorest
从不拘一格的2.0定义生成一个csharp sdk,我想知道是否有可能使生成的子类覆盖具有不同类型的父级属性。
招摇示例:
{
"swagger": "2.0",
"info": {
"version": "1",
"title": "My API"
},
"schemes": [
"https"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/myResource": {
"post": {
"parameters": [
{
"name": "myResource_data",
"in": "body",
"schema": {
"$ref": "#/definitions/myResourceCreateBody"
},
"required": true
}
],
"responses": {
"201": {
"description": "myResource response",
"schema": {
"$ref": "#/definitions/myResourceResponseExtended"
}
}
}
}
}
},
"definitions": {
"metaResponse": {
"type": "object",
"description": "Response metadata.",
"required": [
"api_version"
],
"properties": {
"api_version": {
"type": "string"
}
},
"x-services": [
"shared"
]
},
"extendedMetaResponse": {
"allOf": [
{
"$ref": "#/definitions/metaResponse"
},
{
"type": "object",
"properties": {
"myExtendedProp": {
"type": "string"
}
}
}
],
"x-services": [
"shared"
]
},
"myResourceResponse": {
"type": "object",
"required": [
"meta"
],
"additionalProperties": false,
"properties": {
"meta": {
"$ref": "#/definitions/metaResponse"
}
},
"x-services": [
"myResource"
]
},
"myResourceResponseExtended": {
"allOf": [
{
"$ref": "#/definitions/myResourceResponse"
},
{
"type": "object",
"properties": {
"meta": {
"$ref": "#/definitions/extendedMetaResponse"
}
}
}
],
"x-services": [
"myResource"
]
},
"myResourceCreateBody": {
"type": "object",
"required": [
"myResource_id"
],
"additionalProperties": false,
"properties": {
"myResource_id": {
"type": "string",
"description": "myResource identifier"
}
},
"x-services": [
"myResource"
]
}
}
}
哪个生成以下C#基类:
public partial class MyResourceResponse
{
public MyResourceResponse()
{
CustomInit();
}
public MyResourceResponse(MetaResponse meta)
{
Meta = meta;
CustomInit();
}
partial void CustomInit();
[JsonProperty(PropertyName = "meta")]
public MetaResponse Meta { get; set; }
public virtual void Validate()
{
if (Meta == null)
{
throw new ValidationException(ValidationRules.CannotBeNull, "Meta");
}
if (Meta != null)
{
Meta.Validate();
}
}
}
}
以及以下子类:
public partial class MyResourceResponseExtended : MyResourceResponse
{
public MyResourceResponseExtended()
{
CustomInit();
}
public MyResourceResponseExtended(MetaResponse meta)
: base(meta)
{
CustomInit();
}
partial void CustomInit();
public override void Validate()
{
base.Validate();
}
}
但是我想要的输出是让MyResourceResponseExtended
用类型为Meta
的{{1}}属性覆盖Meta
属性,以显示其附加属性。
例如,我想要的输出将是:
MetaResponseExtended
在Swagger 2.0中是否有更好的方法来定义它? 这是Autorest的错误/局限性吗?
谢谢! :-)
PS:我曾经考虑过在swagger文件中使用public partial class MyResourceResponseExtended : MyResourceResponse
{
[JsonProperty(PropertyName = "meta")]
public new ExtendedMetaResponse Meta { get; set; }
public MyResourceResponseExtended(ExtendedMetaResponse meta)
: base(meta)
{
Meta = meta;
CustomInit();
}
}
,但是我没有正确使用它,或者它不是专门为该特定目的而设计的。
答案 0 :(得分:1)
您肯定需要使用discriminator
,并使用它来创建多态类型。
要具有多态类型,必须具有一个声明为discriminator
的属性,并且作为父类的子级(即,使用allOf
)的每种类型都必须具有x-ms-discriminator-value
,它可以用作密钥来允许反序列化器选择要反序列化为的正确类型。
简单的例子:
swagger: '2.0'
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
host: petstore.swagger.io
basePath: "/v1"
schemes:
- https
consumes:
- application/json
produces:
- application/json
paths:
"/pets":
put:
summary: Add a pet
operationId: addPet
tags:
- pets
parameters:
- schema:
"$ref": "#/definitions/Pet"
responses:
'200':
description: OK
definitions:
Pet:
properties:
petKind:
type: string
name:
type: string
discriminator: petKind
required:
- name
- petType
Cat:
description: A representation of a cat
x-ms-discriminator-value: CAT
allOf:
- "$ref": "#/definitions/Pet"
- properties:
huntingSkill:
type: string
description: The measured skill for hunting
default: lazy
enum:
- clueless
- lazy
- adventurous
- aggressive
required:
- huntingSkill
Dog:
description: A representation of a dog
x-ms-discriminator-value: DOG
allOf:
- "$ref": "#/definitions/Pet"
- properties:
packSize:
type: integer
format: int32
description: the size of the pack the dog is from
default: 0
minimum: 0
required:
- packSize
Pet
对象具有petKind
属性(DOG
或CAT
),该属性告诉反序列化器使用哪种模型反序列化值。
(在生成的c#中,它将为此使用类的属性。)