是否有一种方法显示所有枚举作为他们的字符串值在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
}
使全球
从文档中可以看出:
httpConfiguration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "A title for your API");
c.DescribeAllEnumsAsStrings(); // this will do the trick
});
特定属性的Enum/字符串转换
另外,如果你想让这种行为只发生在特定的类型和属性上,使用StringEnumConverter:
public class Letter
{
[Required]
public string Content {get; set;}
[Required]
[EnumDataType(typeof(Priority))]
[JsonConverter(typeof(StringEnumConverter))]
public Priority Priority {get; set;}
}
如果你使用的是Newtonsoft和Swashbuckle v5.0.0或更高版本
你还需要这个包:
Swashbuckle.AspNetCore.Newtonsoft
在你的创业公司里:
services.AddSwaggerGenNewtonsoftSupport(); // explicit opt-in - needs to be placed after AddSwaggerGen()
这里有文档:https://github.com/domaindrivendev/Swashbuckle.AspNetCore#systemtextjson-stj-vs-newtonsoft
我在这里找到了不错的解决方法:
@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));
model.Type = "string";
model.Format = null;
});
}
}
}
在Startup.cs中:
services.AddSwaggerGen(options =>
{
options.SchemaFilter<EnumSchemaFilter>();
}
注意:当枚举以int形式生成json时使用此解决方案(StringEnumConverter不使用或不能使用)。Swagger将显示枚举名称,并将字符串值传递给API,幸运的是ASP。NET Core可以将enum值作为int和字符串处理,其中字符串值必须是区分大小写的enum名称(例如,对于enum优先级。低,ASP。NET Core接受字符串值Low, Low, Low等)。
我已经修改了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中配置。
对于我们正在寻找的东西,我在其他答案中发现了一些缺点,所以我想我将提供我自己的看法。我们使用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
}
我们将使用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中使用。净的核心。在ConfigureServices中的Startup.cs中配置它:
services.AddControllers()
.AddJsonOptions(opt => opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverterWithAttributeSupport()));
最后,我们需要在Swashbuckle中注册我们的缺血afilter,所以也在ConfigureServices()中添加以下内容:
services.AddSwaggerGen(c => {
c.SchemaFilter<DescribeEnumMemberValues>();
});