Настройка Swashbuckle для использования встроенной схемы - PullRequest
0 голосов
/ 08 октября 2019

С 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 Ответ

1 голос
/ 11 октября 2019

Возьмите общее правило Переопределить схему для определенных типов от Swashbuckle, здесь 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

...