配置Swashbuckle以使用内联架构

时间:2019-10-08 10:57:18

标签: asp.net-core swashbuckle

有了SwashBuckle,我们有一个项目正在为数组/列表创建内联模式:

对,它会返回如下内容:

"200": {
    "description": "Success",
    "schema": {
        "uniqueItems": false,
        "type": "array",
        "items": {
            "$ref": "#/definitions/SwaggerGenerationSample.Models.Response.Employee"
        }
    }
}

我们想要这样的东西:

"200": {
    "description": "Success",
    "schema": {
        "$ref": "#/definitions/EmployeeArray"
    }
}
...
"definitions": {
    "EmployeeArray": {
        "uniqueItems": false,
        "type": "array",
        "items": {
            "$ref": "#/definitions/SwaggerGenerationSample.Models.Response.Employee"
        }
    }
}

我们应该在SwashBuckle中配置什么以获得上述结果?我创建了一个示例项目来重现该问题:https://github.com/mvdiemen/SwaggerArrayGenerationExample

1 个答案:

答案 0 :(得分:1)

从Swashbuckle(此处为Override Schema for Specific Types)中获取ISchemaFilter的一般准则。

您想要的是提供自己的显式架构。对于您的示例项目,对于任何数组,我们都可以使用:

/**
 * code dependencies:
 * netcoreapp2.1
 * Microsoft.AspNetCore.App;2.1.*
 * Swashbuckle.AspNetCore;4.0.1
 */
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace SwaggerGenerationSample
{
    public class ArraySchemaFilter : ISchemaFilter
    {
        public void Apply(Schema schema, SchemaFilterContext context)
        {
            // has to be changed to enumerable later on...
            if (context.SystemType.IsArray && context.SystemType.HasElementType)
            {
                // could be generalized to any T[], for now ...
                var elemType = context.SystemType.GetElementType();
                if (elemType != typeof(SwaggerGenerationSample.Models.Response.Employee)) return;

                var name = elemType.Name + "Array";
                // add if not done already
                if (!context.SchemaRegistry.Definitions.ContainsKey(name))
                {
                    context.SchemaRegistry.Definitions.Add(
                        name,
                        new Schema
                        {
                            UniqueItems = schema.UniqueItems,
                            Type = schema.Type,
                            Items = schema.Items,
                        });
                }

                // and clear the schema for the endpoint...
                schema.UniqueItems = null;
                schema.Type = null;
                schema.Items = null;
                schema.Ref = "#/definitions/" + name;
            }
        }
    }
}

我们需要在启动时添加过滤器。

public void ConfigureServices(IServiceCollection services)
{
    services.AddSwaggerGen(config =>
    {
        /* your config omitted for brevity */
        config.SchemaFilter<ArraySchemaFilter>();
    }
}

要使其正常工作,我们需要将端点从IEnumerable<T>“调整”到T[]

public class EmployeeController : ControllerBase
{
    [SwaggerResponse((int)HttpStatusCode.OK, Type = typeof(Models.Response.Employee[]))]
    /* other attributes omitted for brevity */
    public async Task<IActionResult> GetEmployees(string companyId)
    {
        return Ok(GetEmployees());
    }
}

运行该应用,并且swagger.json应该包含所请求的架构。 为您准备的作业是用IEnumerable<>替换数组限制,但是上面的代码足以作为概念证明。

友好提醒

如果升级到 .Net Core 3 (或更高版本),则必须更新代码-非常有可能。并使用 Swashbuckle.AspNetCore  5 即将打破的消息已经宣布[^ 1]。

[^ 1]:请参见此处的发行说明:https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases/tag/v5.0.0-rc4