是否有一种方法显示所有枚举作为他们的字符串值在swagger而不是他们的int值?

我希望能够提交POST动作,并根据它们的字符串值放置枚举,而不必每次都查看enum。

我尝试了DescribeAllEnumsAsStrings,但服务器然后接收字符串而不是enum值,这不是我们要寻找的。

有人解决了吗?

编辑:

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
}

当前回答

要在swagger中以字符串形式显示枚举,请在ConfigureServices中添加以下行来配置JsonStringEnumConverter:

services.AddControllers().AddJsonOptions(options =>
            options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));

如果你想以字符串和int值的形式显示枚举,你可以尝试创建一个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}")));
        }
    }
}

配置SwaggerGen使用上面的SchemaFilter:

services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo
            {
                Version = "v1",
                Title = "ToDo API",
                Description = "A simple example ASP.NET Core Web API",
                TermsOfService = new Uri("https://example.com/terms"),
                Contact = new OpenApiContact
                {
                    Name = "Shayne Boyer",
                    Email = string.Empty,
                    Url = new Uri("https://twitter.com/spboyer"),
                },
                License = new OpenApiLicense
                {
                    Name = "Use under LICX",
                    Url = new Uri("https://example.com/license"),
                }
            });
              
            c.SchemaFilter<EnumSchemaFilter>();
        });

其他回答

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来实现。看起来除了枚举转换器支持之外,没有这个包其他一切都很好。

在这里搜索答案后,我发现了在模式中显示枚举的问题的部分解决方案[SomeEnumString = 0, AnotherEnumString = 1],但与此相关的所有答案都只是部分正确的,正如@OhWelp在其中一个评论中提到的那样。

下面是。net core的完整解决方案(2、3,目前在6上工作):

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

                var names = Enum.GetNames(context.Type).ToList();

                names.ForEach(name => model.Enum.Add(new OpenApiString($"{GetEnumIntegerValue(name, context)} = {name}")));


                 // the missing piece that will make sure that the new schema will not replace the mock value with a wrong value 
                // this is the default behavior - the first possible enum value as a default "example" value
                model.Example = new OpenApiInteger(GetEnumIntegerValue(names.First(), context));
            }
        }

        private int GetEnumIntegerValue(string name, SchemaFilterContext context) => Convert.ToInt32(Enum.Parse(context.Type, name));
    }

在启动/程序中:

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

编辑:对代码进行了一些重构,如果你想看到原始版本,它与其余的答案更相似,请检查编辑的年表。

我想在. 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)}";
    }
}

然后将它添加到Startup.cs中的ConfigureServices方法中:

c.DocumentFilter<EnumDocumentFilter>();

ASP。NET Core 6 / ASP。NET Core 7

在你的程序中。cs:

builder.Services.AddControllers().AddJsonOptions(options =>
{
    options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});

请注意:

descripbeallenumsasstrings已经过时

简单的解决方案。这对我很管用。

   using System.Text.Json.Serialization;
    
    
    [JsonConverter(typeof(JsonStringEnumConverter))]
    public enum Priority
    {
        Low, 
        Medium,
        High
    }