是否有一种方法显示所有枚举作为他们的字符串值在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
}
如果有人感兴趣,我已经修改了代码的工作
.NET CORE 3和Swagger 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 (IOpenApiAny enumOption in enums)
{
if (enumOption is OpenApiString @string)
{
string enumString = @string.Value;
enumDescriptions.Add(string.Format("{0} = {1}", (int)Enum.Parse(enumType, enumString), enumString));
}
else if (enumOption is OpenApiInteger integer)
{
int enumInt = integer.Value;
enumDescriptions.Add(string.Format("{0} = {1}", enumInt, Enum.GetName(enumType, enumInt)));
}
}
return string.Join(", ", enumDescriptions.ToArray());
}
}
我得到了它的工作。net 6 Web API使用以下代码从其他答案在这里:
1 -创建一个DocumentFilter
/// <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, OperationType.Patch };
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)
{
var enumType = GetEnumTypeByName(param.Schema.Reference.Id);
var names = Enum.GetNames(enumType).ToList();
param.Description += string.Join(", ", names.Select(name => $"{Convert.ToInt32(Enum.Parse(enumType, name))} - {name}").ToList());
}
}
}
private static Type GetEnumTypeByName(string enumTypeName)
{
if (string.IsNullOrEmpty(enumTypeName))
{
return null;
}
try
{
return AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Single(x => x.FullName != null
&& x.Name == enumTypeName);
}
catch (InvalidOperationException e)
{
throw new Exception($"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.Value} - {Enum.GetName(enumType, x.Value)}"));
}
}
2 -将其添加到Program.cs文件中
services.AddSwaggerGen(config =>
{
config.DocumentFilter<SwaggerEnumDocumentFilter>();
})
我已经修改了Hosam Rehani的答案,以使用可空枚举和枚举的收集。只有当属性的名称与其类型完全一致时,前面的答案才有效。下面的代码解决了所有这些问题。
它适用于。net core 3。X和swagger。
在某些情况下,不搜索enum类型两次会更有效。
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< swaggeraddenumdescripts> ();在Startup.cs中配置。
在。net 6与NSwag和System.Text.Json为我工作:
services.AddControllersWithViews()
.AddJsonOptions(o => o.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()))
and
services.AddOpenApiDocument(configure =>
{
...
configure.GenerateEnumMappingDescription = true;
});
它接受int-s和字符串,在open-api和.ts客户端生成带有名称的枚举,并在SwaggerUI中显示带有名称的枚举
export enum PaymentDirection {
Input = "Input",
Output = "Output",
}