是否有一种方法显示所有枚举作为他们的字符串值在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和. net版本6的答案,我遇到了一些问题。x工作。我想继续为枚举使用整数值,但也要显示可能值的列表(以可读的格式)。所以这是我的修改版本(包括一些答案的部分),也许它可以为你们节省一些时间;)
附注:还有一些改进的空间,你也应该检查方法“GetEnumTypeByName”的逻辑是否适合你。在我的情况下,我想主要更新描述仅为项目内部和唯一的枚举。
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Models.Api;
using Swashbuckle.AspNetCore.SwaggerGen;
/// <summary>
/// Add enum value descriptions to Swagger
/// </summary>
public class SwaggerEnumDocumentFilter : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
// add enum descriptions to result models
foreach (var property in swaggerDoc.Components.Schemas)
{
var propertyEnums = property.Value.Enum;
if (propertyEnums is { Count: > 0 })
{
property.Value.Description += DescribeEnum(propertyEnums, property.Key);
}
}
if (swaggerDoc.Paths.Count <= 0)
{
return;
}
// add enum descriptions to input parameters
foreach (var pathItem in swaggerDoc.Paths.Values)
{
DescribeEnumParameters(pathItem.Parameters);
var affectedOperations = new List<OperationType> { OperationType.Get, OperationType.Post, OperationType.Put };
foreach (var operation in pathItem.Operations)
{
if (affectedOperations.Contains(operation.Key))
{
DescribeEnumParameters(operation.Value.Parameters);
}
}
}
}
private static void DescribeEnumParameters(IList<OpenApiParameter> parameters)
{
if (parameters == null) return;
foreach (var param in parameters)
{
if (param.Schema.Reference != null)
{
param.Description += DescribeEnum(param.Schema.Reference.Id);
}
}
}
private static Type GetEnumTypeByName(string enumTypeName)
{
if (string.IsNullOrEmpty(enumTypeName))
{
return null;
}
try
{
var projectNamespaceRoot = "MyProject.";
return AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Single(x => x.FullName != null
&& x.FullName.StartsWith(projectNamespaceRoot)
&& x.Name == enumTypeName);
}
catch (InvalidOperationException _)
{
throw new ApiException($"SwaggerDoc: Can not find a unique Enum for specified typeName '{enumTypeName}'. Please provide a more unique enum name.");
}
}
private static string DescribeEnum(IEnumerable<IOpenApiAny> enums, string propertyTypeName)
{
var enumType = GetEnumTypeByName(propertyTypeName);
if (enumType == null)
{
return null;
}
var parsedEnums = new List<OpenApiInteger>();
foreach (var @enum in enums)
{
if (@enum is OpenApiInteger enumInt)
{
parsedEnums.Add(enumInt);
}
}
return string.Join(", ", parsedEnums.Select(x => $"{x} = {Enum.GetName(enumType, x.Value)}"));
}
}
正如其他人已经提到的,你必须在你的Swagger设置中注册这个过滤器:
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
// some configuration
});
options.DocumentFilter<SwaggerEnumDocumentFilter>();
});
asp.net core 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 Version 5.0.0-rc4似乎还没有准备好支持这个功能。所以我们需要在Swashbuckle配置文件中使用一个选项(已弃用),直到它像Newtonsoft库一样支持和反映它。
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
c.DescribeAllEnumsAsStrings();
这个答案和其他答案之间的区别是只使用Microsoft JSON库而不是Newtonsoft。
我想我也有类似的问题。我正在寻找swagger与int ->字符串映射一起生成枚举。API必须接受整型。swagger-ui不那么重要,我真正想要的是代码生成与另一边的“真实”enum(在这种情况下使用改装的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上产生如下的结果,这样至少你可以“看到你在做什么”:
ASP。NET Core 3与Microsoft JSON库(System.Text.Json)
在Startup.cs / ConfigureServices ():
services
.AddControllersWithViews(...) // or AddControllers() in a Web API
.AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
ASP。NET Core 3和Json。NET (Newtonsoft.Json)库
安装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()));
Pre-ASP。网络核心
httpConfiguration
.EnableSwagger(c =>
{
c.DescribeAllEnumsAsStrings();
});