gpt4 book ai didi

c# - 如何使用 Swashbuckle 在 Swagger API 文档/OpenAPI 规范中包含子类?

转载 作者:可可西里 更新时间:2023-11-01 03:04:19 28 4
gpt4 key购买 nike

我在 C# 中有一个 Asp.Net Web API 5.2 项目并使用 Swashbuckle 生成文档。

我有一个包含继承的模型,例如具有来自 Animal 抽象类的 Animal 属性以及从它派生的 Dog 和 Cat 类。

Swashbuckle 仅显示 Animal 类的模式,因此我尝试使用 ISchemaFilter(他们也建议这样做)但我无法使其工作,而且我找不到合适的示例。

有人可以帮忙吗?

最佳答案

似乎 Swashbuckle 没有正确实现多态性,我理解作者关于子类作为参数的观点(如果一个 Action 需要一个 Animal 类并且如果你用狗对象或猫对象调用它时表现不同,那么你应该有 2 个不同的操作...) 但作为返回类型,我认为返回 Animal 是正确的,对象可以是 Dog 或 Cat 类型。

因此,为了描述我的 API 并根据正确的指南生成适当的 JSON 模式(请注意我描述鉴别器的方式,如果您有自己的鉴别器,您可能需要特别更改该部分),我使用文档和架构过滤器如下:

SwaggerDocsConfig configuration;
.....
configuration.DocumentFilter<PolymorphismDocumentFilter<YourBaseClass>>();
configuration.SchemaFilter<PolymorphismSchemaFilter<YourBaseClass>>();
.....

public class PolymorphismSchemaFilter<T> : ISchemaFilter
{
private readonly Lazy<HashSet<Type>> derivedTypes = new Lazy<HashSet<Type>>(Init);

private static HashSet<Type> Init()
{
var abstractType = typeof(T);
var dTypes = abstractType.Assembly
.GetTypes()
.Where(x => abstractType != x && abstractType.IsAssignableFrom(x));

var result = new HashSet<Type>();

foreach (var item in dTypes)
result.Add(item);

return result;
}

public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
{
if (!derivedTypes.Value.Contains(type)) return;

var clonedSchema = new Schema
{
properties = schema.properties,
type = schema.type,
required = schema.required
};

//schemaRegistry.Definitions[typeof(T).Name]; does not work correctly in SwashBuckle
var parentSchema = new Schema { @ref = "#/definitions/" + typeof(T).Name };

schema.allOf = new List<Schema> { parentSchema, clonedSchema };

//reset properties for they are included in allOf, should be null but code does not handle it
schema.properties = new Dictionary<string, Schema>();
}
}

public class PolymorphismDocumentFilter<T> : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, System.Web.Http.Description.IApiExplorer apiExplorer)
{
RegisterSubClasses(schemaRegistry, typeof(T));
}

private static void RegisterSubClasses(SchemaRegistry schemaRegistry, Type abstractType)
{
const string discriminatorName = "discriminator";

var parentSchema = schemaRegistry.Definitions[SchemaIdProvider.GetSchemaId(abstractType)];

//set up a discriminator property (it must be required)
parentSchema.discriminator = discriminatorName;
parentSchema.required = new List<string> { discriminatorName };

if (!parentSchema.properties.ContainsKey(discriminatorName))
parentSchema.properties.Add(discriminatorName, new Schema { type = "string" });

//register all subclasses
var derivedTypes = abstractType.Assembly
.GetTypes()
.Where(x => abstractType != x && abstractType.IsAssignableFrom(x));

foreach (var item in derivedTypes)
schemaRegistry.GetOrRegister(item);
}
}

前面的代码实现的是指定here ,在“支持多态性的模型”部分。它基本上产生如下内容:

{
"definitions": {
"Pet": {
"type": "object",
"discriminator": "petType",
"properties": {
"name": {
"type": "string"
},
"petType": {
"type": "string"
}
},
"required": [
"name",
"petType"
]
},
"Cat": {
"description": "A representation of a cat",
"allOf": [
{
"$ref": "#/definitions/Pet"
},
{
"type": "object",
"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",
"allOf": [
{
"$ref": "#/definitions/Pet"
},
{
"type": "object",
"properties": {
"packSize": {
"type": "integer",
"format": "int32",
"description": "the size of the pack the dog is from",
"default": 0,
"minimum": 0
}
},
"required": [
"packSize"
]
}
]
}
}
}

关于c# - 如何使用 Swashbuckle 在 Swagger API 文档/OpenAPI 规范中包含子类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34397349/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com