是否有一种方法显示所有枚举作为他们的字符串值在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
我想在. 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 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。
这在标准的OpenAPI中是不可能的。枚举只使用它们的字符串值进行描述。
幸运的是,您可以使用客户机生成器使用的一些非标准扩展来实现这一点。
NSwag支持x-enumNames
AutoRest支持x-ms-enum。
Openapi-generator支持x-enum-varnames
其他生成器可能支持这些扩展之一或有自己的扩展。
要为NSwag生成x-enumNames,请创建以下模式过滤器:
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>();
});
对于我们正在寻找的东西,我在其他答案中发现了一些缺点,所以我想我将提供我自己的看法。我们使用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>();
});