Swagger UI Web Api文档将枚举形式表示为字符串吗?


107

有没有一种方法可以将所有枚举显示为字符串形式,而不是int形式?

我希望能够提交POST操作并根据其字符串值放置枚举,而不必每次都查看该枚举。

我试过了,DescribeAllEnumsAsStrings但是服务器然后接收字符串而不是我们想要的枚举值。

有人解决了吗?

编辑:

public class Letter 
{
    [Required]
    public string Content {get; set;}

    [Required]
    [EnumDataType(typeof(Priority))]
    public Priority Priority {get; set;}
}


public class LettersController : ApiController
{
    [HttpPost]
    public IHttpActionResult SendLetter(Letter letter)
    {
        // Validation not passing when using DescribeEnumsAsStrings
        if (!ModelState.IsValid)
            return BadRequest("Not valid")

        ..
    }

    // In the documentation for this request I want to see the string values of the enum before submitting: Low, Medium, High. Instead of 0, 1, 2
    [HttpGet]
    public IHttpActionResult GetByPriority (Priority priority)
    {

    }
}


public enum Priority
{
    Low, 
    Medium,
    High
}

1
您是否希望模式将值描述为字符串,然后将整数发布到服务器?JSON.net可以很好地处理这两个值,那么仅整数版本是否有明确要求?我认为Swagger不支持同时包含字符串和整数值的枚举类型。
Hux

1
您的预期行为尚不清楚,能否通过示例更好地说明您希望Swagger UI显示什么以及想要将POST / PUT放到Web API中?
Federico Dipuma '16

此外,如果我有在URL中使用枚举的GET方法,我希望该方案将其描述为建议值下拉列表中的字符串

为什么整数验证失败?该类型应为模型中的枚举,并且json媒体格式化程序将正确处理字符串或整数。如果用示例更新问题,它将帮助我们理解验证失败的原因。
Hux

4
如果它是一个标志枚举,则它必须是数字,除非为每个可能的标志组合定义了枚举值。傻乎乎的是,swagger不会同时显示每个枚举的名称和值,而是只显示数字(无用)或仅显示名称(同样,对于必须指定为数字的标志无效)。
Triynko,

Answers:


188

文档

httpConfiguration
    .EnableSwagger(c => 
        {
            c.SingleApiVersion("v1", "A title for your API");

            c.DescribeAllEnumsAsStrings(); // this will do the trick
        });

另外,如果只希望对特定类型和属性使用此行为,请使用StringEnumConverter:

public class Letter 
{
    [Required]
    public string Content {get; set;}

    [Required]
    [EnumDataType(typeof(Priority))]
    [JsonConverter(typeof(StringEnumConverter))]
    public Priority Priority {get; set;}
}

5
这对我不起作用。[EnumDataType(typeof(Priority))] [JsonConverter(typeof(StringEnumConverter))]
Lineker

@NH。是的,我使用了newtonsoft.json
Lineker

@Lineker,按照此指南将您的错误作为新问题发布:stackoverflow.com/help/mcve
NH。

谢谢!我想我可能也会在源中留下您的评论#thiswilldothetrick
Simon_Weaver

5
DescribeAllEnumsAsStrings用于对象属性,甚至查询控制器操作的参数。但是,使用EnumDataTypeAttributeJsonConverter(typeof(StringEnumConverter))不适用于我。
bugged87 '18 -10-23

89

对于带有Microsoft JSON库(System.Text.Json)的ASP.NET Core 3

在Startup.cs / ConfigureServices()中:

services
    .AddControllersWithViews(...) // or AddControllers() in a Web API
    .AddJsonOptions(options => 
        options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));

对于带有Json.NET(Newtonsoft.Json)库的ASP.NET Core 3

安装Swashbuckle.AspNetCore.Newtonsoft软件包。

在Startup.cs / ConfigureServices()中:

services
    .AddControllersWithViews(...)
    .AddNewtonsoftJson(options => 
        options.SerializerSettings.Converters.Add(new StringEnumConverter()));
// order is vital, this *must* be called *after* AddNewtonsoftJson()
services.AddSwaggerGenNewtonsoftSupport();

对于ASP.NET Core 2

在Startup.cs / ConfigureServices()中:

services
    .AddMvc(...)
    .AddJsonOptions(options => 
        options.SerializerSettings.Converters.Add(new StringEnumConverter()));

ASP.NET之前的核心

httpConfiguration
    .EnableSwagger(c => 
        {
            c.DescribeAllEnumsAsStrings();
        });

4
使用options.SerializerSettings.Converters.Add(new StringEnumConverter()))的问题是您更改了所有方法的json,而不仅是Sawshbuckle。
纪尧姆

有没有人有针对Azure Functions v2和/或v3的解决方案?
丹·弗里德曼

@DanFriedman考虑到Swashbuckle根本无法与Azure Functions一起使用,您很不走运。
伊恩·坎普

@IanKemp该AzureExtensions.Swashbuckle软件包提供了第三方支持,但像@DanFriedman一样,我无法按预期方式进行枚举到字符串的工作
wolfyuk

40

所以我想我也有类似的问题。我在寻找招摇以生成枚举以及int->字符串映射。API必须接受int。swagger-ui无关紧要,我真正想要的是在另一侧带有“真实”枚举的代码生成(在这种情况下,Android应用程序使用了改进)。

因此,根据我的研究,这最终似乎是Swagger使用的OpenAPI规范的限制。不能为枚举指定名称和数字。

我发现要遵循的最佳问题是https://github.com/OAI/OpenAPI-Specification/issues/681,它看起来像“也许很快”,但随后必须将Swagger更新,在我的情况下为Swashbuckle好。

目前,我的解决方法是实现一个文档过滤器,该过滤器查找枚举并用枚举的内容填充相关的描述。

        GlobalConfiguration.Configuration
            .EnableSwagger(c =>
                {
                    c.DocumentFilter<SwaggerAddEnumDescriptions>();

                    //disable this
                    //c.DescribeAllEnumsAsStrings()

SwaggerAddEnumDescriptions.cs:

using System;
using System.Web.Http.Description;
using Swashbuckle.Swagger;
using System.Collections.Generic;

public class SwaggerAddEnumDescriptions : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
    {
        // add enum descriptions to result models
        foreach (KeyValuePair<string, Schema> schemaDictionaryItem in swaggerDoc.definitions)
        {
            Schema schema = schemaDictionaryItem.Value;
            foreach (KeyValuePair<string, Schema> propertyDictionaryItem in schema.properties)
            {
                Schema property = propertyDictionaryItem.Value;
                IList<object> propertyEnums = property.@enum;
                if (propertyEnums != null && propertyEnums.Count > 0)
                {
                    property.description += DescribeEnum(propertyEnums);
                }
            }
        }

        // add enum descriptions to input parameters
        if (swaggerDoc.paths.Count > 0)
        {
            foreach (PathItem pathItem in swaggerDoc.paths.Values)
            {
                DescribeEnumParameters(pathItem.parameters);

                // head, patch, options, delete left out
                List<Operation> possibleParameterisedOperations = new List<Operation> { pathItem.get, pathItem.post, pathItem.put };
                possibleParameterisedOperations.FindAll(x => x != null).ForEach(x => DescribeEnumParameters(x.parameters));
            }
        }
    }

    private void DescribeEnumParameters(IList<Parameter> parameters)
    {
        if (parameters != null)
        {
            foreach (Parameter param in parameters)
            {
                IList<object> paramEnums = param.@enum;
                if (paramEnums != null && paramEnums.Count > 0)
                {
                    param.description += DescribeEnum(paramEnums);
                }
            }
        }
    }

    private string DescribeEnum(IList<object> enums)
    {
        List<string> enumDescriptions = new List<string>();
        foreach (object enumOption in enums)
        {
            enumDescriptions.Add(string.Format("{0} = {1}", (int)enumOption, Enum.GetName(enumOption.GetType(), enumOption)));
        }
        return string.Join(", ", enumDescriptions.ToArray());
    }

}

这会在swagger-ui上产生类似以下内容的内容,因此至少您可以“看到自己在做什么”: 在此处输入图片说明


1
+1我一直在为枚举添加描述(只是为了“描述枚举”),却从未想到过。我已经有了杂项过滤器,但是正在寻找更“有机”的东西,但是没有任何支持。好吧,一路过滤器:)
NSGaga-大部分时间无效

谢谢!我在项目中使用了此功能,但对其进行了修改以与.NET Core一起使用。我添加了实现作为答案。
加布里埃尔·卢西

27

ASP.NET Core 3.1

要使用Newtonsoft JSON将枚举生成为字符串,您必须通过添加AddSwaggerGenNewtonsoftSupport()以下内容显式添加Newtonsoft支持:

services.AddMvc()
    ...
    .AddNewtonsoftJson(opts =>
    {
        opts.SerializerSettings.Converters.Add(new StringEnumConverter());
    });


services.AddSwaggerGen(...);
services.AddSwaggerGenNewtonsoftSupport(); //

可通过新软件包来获得Swashbuckle.AspNetCore.Newtonsoft。除了枚举转换器支持之外,如果没有此软件包,其他一切似乎都可以正常工作。


1
它有助于全局设置此约定,但是如果您只需要将此规则应用于某些类型的枚举,则需要仔细阅读此问题。TL; DR:不可能仅将新的StringEnumConverter()应用于属性,但可以将其应用于整个枚举类型。
A. Tretiakov

1
我想如果我们谈论陷阱,也不可能使用完全自定义的转换器。Swagger不会通过自定义转换器运行枚举值。它只是认为StringEnumConverter是一种特殊情况。
罗曼·斯塔科夫

22

我想在.NET Core应用程序中使用rory_za的答案,但是我不得不对其进行一些修改以使其起作用。这是我为.NET Core设计的实现。

我也对其进行了更改,因此它不假定基础类型为int,并且在值之间使用新行以方便阅读。

/// <summary>
/// Add enum value descriptions to Swagger
/// </summary>
public class EnumDocumentFilter : IDocumentFilter {
    /// <inheritdoc />
    public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context) {
        // add enum descriptions to result models
        foreach (var schemaDictionaryItem in swaggerDoc.Definitions) {
            var schema = schemaDictionaryItem.Value;
            foreach (var propertyDictionaryItem in schema.Properties) {
                var property = propertyDictionaryItem.Value;
                var propertyEnums = property.Enum;
                if (propertyEnums != null && propertyEnums.Count > 0) {
                    property.Description += DescribeEnum(propertyEnums);
                }
            }
        }

        if (swaggerDoc.Paths.Count <= 0) return;

        // add enum descriptions to input parameters
        foreach (var pathItem in swaggerDoc.Paths.Values) {
            DescribeEnumParameters(pathItem.Parameters);

            // head, patch, options, delete left out
            var possibleParameterisedOperations = new List<Operation> {pathItem.Get, pathItem.Post, pathItem.Put};
            possibleParameterisedOperations.FindAll(x => x != null)
                .ForEach(x => DescribeEnumParameters(x.Parameters));
        }
    }

    private static void DescribeEnumParameters(IList<IParameter> parameters) {
        if (parameters == null) return;

        foreach (var param in parameters) {
            if (param is NonBodyParameter nbParam && nbParam.Enum?.Any() == true) {
                param.Description += DescribeEnum(nbParam.Enum);
            } else if (param.Extensions.ContainsKey("enum") && param.Extensions["enum"] is IList<object> paramEnums &&
                paramEnums.Count > 0) {
                param.Description += DescribeEnum(paramEnums);
            }
        }
    }

    private static string DescribeEnum(IEnumerable<object> enums) {
        var enumDescriptions = new List<string>();
        Type type = null;
        foreach (var enumOption in enums) {
            if (type == null) type = enumOption.GetType();
            enumDescriptions.Add($"{Convert.ChangeType(enumOption, type.GetEnumUnderlyingType())} = {Enum.GetName(type, enumOption)}");
        }

        return $"{Environment.NewLine}{string.Join(Environment.NewLine, enumDescriptions)}";
    }
}

然后将其添加到ConfigureServicesStartup.cs中的方法中:

c.DocumentFilter<EnumDocumentFilter>();

可以删除下面的Enum:Array [6]吗?
Softlion

4
很好的解决方案,但是扩展DescribeEnumParameters在我的项目中是空的。我不得不将其强制转换paramNonBodyParameter并检查其中的枚举:if (param is NonBodyParameter nbParam && nbParam.Enum?.Any() == true) { param.Description += DescribeEnum(nbParam.Enum); }
Rabban

在我的项目中,扩展名也为空,使用@Rabban解决方案。
卡洛斯·贝普勒

1
@Rabban我更新了代码以包含该代码。您能验证我放在正确的位置吗?我没有这个问题。也许新版本改变了事情。
加布里埃尔·卢西

@GabrielLuci确认并批准;)
Rabban

12

使用asp.net核心3

using System.Text.Json.Serialization;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
         services.AddControllers().AddJsonOptions(options =>
             options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));

但是似乎Swashbuckle版本5.0.0-rc4尚未准备好支持该版本。因此,我们需要在Swashbuckle配置文件中使用一个选项(不建议使用),直到它像Newtonsoft库一样支持并反映它。

public void ConfigureServices(IServiceCollection services)
{ 
      services.AddSwaggerGen(c =>
      {
            c.DescribeAllEnumsAsStrings();

此答案与其他答案之间的区别是仅使用Microsoft JSON库而不是Newtonsoft。


嘿@Bashir,是否有swachbuckle问题来跟踪缺少该支持的情况?
伯纳德·范德·贝克

嗨@ bernard-vander-beken,我没有举报,但我想有。如果我们能找到它并将它添加到这篇文章中以供以后更新,则很好。
巴希尔·莫曼


10

.NET CORE 3.1和SWAGGER 5

如果您需要一个简单的解决方案来选择性地使枚举作为字符串传递:

using System.Text.Json.Serialization;


[JsonConverter(typeof(JsonStringEnumConverter))]
public enum MyEnum
{
    A, B
}

注意,我们使用System.Text.Json.Serialization名称空间,而不是Newtonsoft.Json


这项工作显示了正确的值,并且在将值转换回枚举时也起作用。请注意,您需要添加NuGet包System.Text.Json
MovGP0

那就是我想要的!因为我只需要将字符串用于单个枚举,DescribeAllEnumsAsStrings并将所有枚举转换为字符串。
Nilay

9

如果有人感兴趣,我已经修改了要使用的代码

.NET CORE 3Swagger V5

    public class SwaggerAddEnumDescriptions : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        // add enum descriptions to result models
        foreach (var property in swaggerDoc.Components.Schemas.Where(x => x.Value?.Enum?.Count > 0))
        {
            IList<IOpenApiAny> propertyEnums = property.Value.Enum;
            if (propertyEnums != null && propertyEnums.Count > 0)
            {
                property.Value.Description += DescribeEnum(propertyEnums, property.Key);
            }
        }

        // add enum descriptions to input parameters
        foreach (var pathItem in swaggerDoc.Paths.Values)
        {
            DescribeEnumParameters(pathItem.Operations, swaggerDoc);
        }
    }

    private void DescribeEnumParameters(IDictionary<OperationType, OpenApiOperation> operations, OpenApiDocument swaggerDoc)
    {
        if (operations != null)
        {
            foreach (var oper in operations)
            {
                foreach (var param in oper.Value.Parameters)
                {
                    var paramEnum = swaggerDoc.Components.Schemas.FirstOrDefault(x => x.Key == param.Name);
                    if (paramEnum.Value != null)
                    {
                        param.Description += DescribeEnum(paramEnum.Value.Enum, paramEnum.Key);
                    }
                }
            }
        }
    }

    private Type GetEnumTypeByName(string enumTypeName)
    {
        return AppDomain.CurrentDomain
            .GetAssemblies()
            .SelectMany(x => x.GetTypes())
            .FirstOrDefault(x => x.Name == enumTypeName);
    }

    private string DescribeEnum(IList<IOpenApiAny> enums, string proprtyTypeName)
    {
        List<string> enumDescriptions = new List<string>();
        var enumType = GetEnumTypeByName(proprtyTypeName);
        if (enumType == null)
            return null;

        foreach (OpenApiInteger enumOption in enums)
        {
            int enumInt = enumOption.Value;

            enumDescriptions.Add(string.Format("{0} = {1}", enumInt, Enum.GetName(enumType, enumInt)));
        }

        return string.Join(", ", enumDescriptions.ToArray());
    }
}

1
这仅在参数类型完全为枚举时有效...不能为空的枚举,枚举的集合等。请检查我的答案是否适合这些情况。
Matyas

4

我只是这样做,而且效果很好!

启动文件

services.AddSwaggerGen(c => {
  c.DescribeAllEnumsAsStrings();
});

Model.cs

public enum ColumnType {
  DATE = 0
}

swagger.json

type: {
  enum: ["DATE"],
  type: "string"
}

希望这对您有所帮助!


2
DescribeAllEnumsAsStrings已弃用
Node.JS,

4

在.net core 3.1和swagger 5.0.0中:

using System.Linq;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace WebFramework.Swagger
{
    public class EnumSchemaFilter : ISchemaFilter
    {
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            if (context.Type.IsEnum)
            {
                var enumValues = schema.Enum.ToArray();
                var i = 0;
                schema.Enum.Clear();
                foreach (var n in Enum.GetNames(context.Type).ToList())
                {
                    schema.Enum.Add(new OpenApiString(n + $" = {((OpenApiPrimitive<int>)enumValues[i]).Value}"));
                    i++;
                }
            }
        }
    }

}

并在Startup.cs中:

services.AddSwaggerGen(options =>
            {
                #region  EnumDesc
                options.SchemaFilter<EnumSchemaFilter>();
                #endregion
            });

结果


4
不利的一面是,执行请求时,API不会仅传递枚举值的int表示形式(例如2),而是将完整的描述作为一个值(例如LogicError = 3)获得,否则将失败。错误的请求,因为它不是枚举的有效值。
Matyas

3

我的带有值的枚举st的变体:

在此处输入图片说明

配置服务:

services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "web server api", Version = "v1" });
                c.SchemaFilter<EnumSchemaFilter>();
            });

过滤:

public class EnumSchemaFilter : ISchemaFilter
    {
        public void Apply(OpenApiSchema model, SchemaFilterContext context)
        {
            if (context.Type.IsEnum)
            {
                model.Enum.Clear();
                Enum.GetNames(context.Type)
                    .ToList()
                    .ForEach(name => model.Enum.Add(new OpenApiString($"{Convert.ToInt64(Enum.Parse(context.Type, name))} - {name}")));
            }
        }
    }

2

在Startup.cs中编写代码

services.AddSwaggerGen(c => {
      c.DescribeAllEnumsAsStrings();
    });

2
Swashbuckle中不推荐使用此选项。建议使用ASP.NET Core选项,然后Swashbuckle可以反映出来。
巴希尔·莫曼

2

我在这里找到了不错的解决方法:

@PauloVetor-使用ShemaFilter像这样解决它:

public class EnumSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema model, SchemaFilterContext context)
    {
        if (context.Type.IsEnum)
        {
            model.Enum.Clear();
            Enum.GetNames(context.Type)
                .ToList()
                .ForEach(n => model.Enum.Add(new OpenApiString(n)));
            }
        }
    }
}

在Startup.cs中:

services.AddSwaggerGen(options =>
{
    options.SchemaFilter<EnumSchemaFilter>();
}

您还应该确保您更新model.Format"string",因为它一般会"int32"
lsuarez

1

.Net Core 3.0

   using Newtonsoft.Json.Converters;

 services
    .AddMvc(options =>
    {
     options.EnableEndpointRouting = false;
     })
    .AddNewtonsoftJson(options => options.SerializerSettings.Converters.Add(new StringEnumConverter()))

1
它使用Newtonsoft代替新的asp.net核心JSON序列化。
巴希尔·莫曼

1

我修改了Hosam Rehani的答案,使其可用于可空枚举以及枚举集合。仅当属性的名称与类型完全相同时,上一个答案也才有效。所有这些问题在下面的代码中得到解决。

它适用于.net core 3.x和swagger5.x。

在某些情况下,不两次搜索枚举类型可能会更有效率。

class SwaggerAddEnumDescriptions : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        // add enum descriptions to result models
        foreach (var property in swaggerDoc.Components.Schemas.Where(x => x.Value?.Enum?.Count > 0))
        {
            IList<IOpenApiAny> propertyEnums = property.Value.Enum;
            if (propertyEnums != null && propertyEnums.Count > 0)
            {
                property.Value.Description += DescribeEnum(propertyEnums, property.Key);
            }
        }

        // add enum descriptions to input parameters
        foreach (var pathItem in swaggerDoc.Paths)
        {
            DescribeEnumParameters(pathItem.Value.Operations, swaggerDoc, context.ApiDescriptions, pathItem.Key);
        }
    }

    private void DescribeEnumParameters(IDictionary<OperationType, OpenApiOperation> operations, OpenApiDocument swaggerDoc, IEnumerable<ApiDescription> apiDescriptions, string path)
    {
        path = path.Trim('/');
        if (operations != null)
        {
            var pathDescriptions = apiDescriptions.Where(a => a.RelativePath == path);
            foreach (var oper in operations)
            {
                var operationDescription = pathDescriptions.FirstOrDefault(a => a.HttpMethod.Equals(oper.Key.ToString(), StringComparison.InvariantCultureIgnoreCase));
                foreach (var param in oper.Value.Parameters)
                {
                    var parameterDescription = operationDescription.ParameterDescriptions.FirstOrDefault(a => a.Name == param.Name);
                    if (parameterDescription != null && TryGetEnumType(parameterDescription.Type, out Type enumType))
                    {
                        var paramEnum = swaggerDoc.Components.Schemas.FirstOrDefault(x => x.Key == enumType.Name);
                        if (paramEnum.Value != null)
                        {
                            param.Description += DescribeEnum(paramEnum.Value.Enum, paramEnum.Key);
                        }
                    }
                }
            }
        }
    }

    bool TryGetEnumType(Type type, out Type enumType)
    {
        if (type.IsEnum)
        {
            enumType = type;
            return true;
        }
        else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
        {
            var underlyingType = Nullable.GetUnderlyingType(type);
            if (underlyingType != null && underlyingType.IsEnum == true)
            {
                enumType = underlyingType;
                return true;
            }
        }
        else
        {
            Type underlyingType = GetTypeIEnumerableType(type);
            if (underlyingType != null && underlyingType.IsEnum)
            {
                enumType = underlyingType;
                return true;
            }
            else
            {
                var interfaces = type.GetInterfaces();
                foreach (var interfaceType in interfaces)
                {
                    underlyingType = GetTypeIEnumerableType(interfaceType);
                    if (underlyingType != null && underlyingType.IsEnum)
                    {
                        enumType = underlyingType;
                        return true;
                    }
                }
            }
        }

        enumType = null;
        return false;
    }

    Type GetTypeIEnumerableType(Type type)
    {
        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
        {
            var underlyingType = type.GetGenericArguments()[0];
            if (underlyingType.IsEnum)
            {
                return underlyingType;
            }
        }

        return null;
    }

    private Type GetEnumTypeByName(string enumTypeName)
    {
        return AppDomain.CurrentDomain
            .GetAssemblies()
            .SelectMany(x => x.GetTypes())
            .FirstOrDefault(x => x.Name == enumTypeName);
    }

    private string DescribeEnum(IList<IOpenApiAny> enums, string proprtyTypeName)
    {
        List<string> enumDescriptions = new List<string>();
        var enumType = GetEnumTypeByName(proprtyTypeName);
        if (enumType == null)
            return null;

        foreach (OpenApiInteger enumOption in enums)
        {
            int enumInt = enumOption.Value;

            enumDescriptions.Add(string.Format("{0} = {1}", enumInt, Enum.GetName(enumType, enumInt)));
        }

        return string.Join(", ", enumDescriptions.ToArray());
    }
}

使用过滤器添加c.DocumentFilter<SwaggerAddEnumDescriptions>();到招摇配置Startup.cs


0

ASP NET解决方案

尽管属性标记为,但在我的api文档中,一个枚举仍然显示为int StringEnumConverter。我们不能为上述所有枚举使用全局设置。在SwaggerConfig中添加此行可解决此问题:

c.MapType<ContactInfoType>(() => new Schema { type = "string", @enum = Enum.GetNames(typeof(ContactInfoType))});

0

在其他答案中,我发现了很多缺点,这是我们想要的,因此,我想就此提出自己的看法。我们正在将ASP.NET Core 3.1与System.Text.Json一起使用,但是我们的方法不管使用的JSON序列化程序如何都有效。

我们的目标是在ASP.NET Core API中接受小写字母大小写的枚举字符串值,并在Swagger中记录相同的值。我们目前正在使用[DataContract][EnumMember],因此方法是从EnumMember值属性中获取低驼峰大小写的值,并全面使用它。

我们的示例枚举:

[DataContract]
public class enum Colors
{
  [EnumMember(Value="brightPink")]
  BrightPink,
  [EnumMember(Value="blue")]
  Blue
}

我们将通过使用ISchemaFilter在Swashbuckle中使用EnumMember值,如下所示:

public class DescribeEnumMemberValues : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (context.Type.IsEnum)
        {
            schema.Enum.Clear();

            //Retrieve each of the values decorated with an EnumMember attribute
            foreach (var member in context.Type.GetMembers())
            {
                var memberAttr = member.GetCustomAttributes(typeof(EnumMemberAttribute), false).FirstOrDefault();
                if (memberAttr != null)
                {
                    var attr = (EnumMemberAttribute) memberAttr;
                    schema.Enum.Add(new OpenApiString(attr.Value));
                }
            }
        }
    }
}

我们正在使用第三方NuGet包(GitHub repo),以确保ASP.NET Core中也使用了这种命名方案。使用以下命令在ConfigureServices中的Startup.cs中对其进行配置:

services.AddControllers()
  .AddJsonOptions(opt => opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverterWithAttributeSupport()));

最后,我们需要在Swashbuckle中注册ISchemaFilter,因此还要在ConfigureServices()中添加以下内容:

services.AddSwaggerGen(c => {
  c.SchemaFilter<DescribeEnumMemberValues>();
});

GetMembers()GetMembers(BindingFlags.Static | BindingFlags.Public)限制为仅将实际声明的枚举属性(例如“ Blue”)限制为更好。如果没有[EnumMember]属性,我还修改了“ else”大小写以返回Member.Name的情况。
user2864740

0

对于标准的OpenAPI,这是不可能的。枚举仅使用其字符串值进行描述。

幸运的是,您可以使用客户端生成器使用的一些非标准扩展来实现。

NSwag支持 x-enumNames

AutoRest支持x-ms-enum

Openapi生成器支持 x-enum-varnames

其他生成器可能支持这些扩展之一或拥有自己的扩展。

x-enumNames为NSwag 生成,请创建以下架构过滤器:

public class EnumSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (context.Type.IsEnum)
        {
            var array = new OpenApiArray();
            array.AddRange(Enum.GetNames(context.Type).Select(n => new OpenApiString(n)));
            // NSwag
            schema.Extensions.Add("x-enumNames", array);
            // Openapi-generator
            schema.Extensions.Add("x-enum-varnames", array);
        }
    }
}

并将其注册为:

services.AddSwaggerGen(options =>
{
    options.SchemaFilter<EnumSchemaFilter>();
});

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.