C# Swagger UI Web Api文档是否将枚举显示为字符串?
是否有一种方法可以将所有枚举显示为它们在swagger中的字符串值,而不是int值 我希望能够提交POST操作并根据其字符串值放置枚举,而不必每次都查看枚举C# Swagger UI Web Api文档是否将枚举显示为字符串?,c#,asp.net-web-api,asp.net-web-api2,swagger-ui,swashbuckle,C#,Asp.net Web Api,Asp.net Web Api2,Swagger Ui,Swashbuckle,是否有一种方法可以将所有枚举显示为它们在swagger中的字符串值,而不是int值 我希望能够提交POST操作并根据其字符串值放置枚举,而不必每次都查看枚举 我尝试了descripeballemsasstrings,但服务器随后会接收字符串,而不是我们要查找的枚举值 有人解决了这个问题吗 编辑: 全局启用 发件人: 特定属性上的枚举/字符串转换 此外,如果您只想在特定类型和属性上使用此行为,请使用StringEnumConverter: public class Letter { [R
我尝试了
descripeballemsasstrings
,但服务器随后会接收字符串,而不是我们要查找的枚举值
有人解决了这个问题吗
编辑:
全局启用
发件人:
特定属性上的枚举/字符串转换
此外,如果您只想在特定类型和属性上使用此行为,请使用StringEnumConverter:
public class Letter
{
[Required]
public string Content {get; set;}
[Required]
[EnumDataType(typeof(Priority))]
[JsonConverter(typeof(StringEnumConverter))]
public Priority Priority {get; set;}
}
如果您使用的是Newtonsoft和Swashback v5.0.0或更高版本
您还需要此软件包:
Swashbuckle.AspNetCore.Newtonsoft
在您的初创公司中:
services.AddSwaggerGenNewtonsoftSupport(); // explicit opt-in - needs to be placed after AddSwaggerGen()
这里有文档:所以我想我也有类似的问题。我正在寻找swagger来生成枚举以及int->string映射。API必须接受int。大摇大摆的ui不那么重要,我真正想要的是在另一端使用“真实”枚举生成代码(在这种情况下,android应用程序使用改型) 所以从我的研究来看,这最终似乎是Swagger使用的OpenAPI规范的一个限制。无法为枚举指定名称和数字 我发现最值得关注的问题是,它看起来像是一个“可能很快”的问题,但随后必须更新“招摇过市”,在我的例子中,也是“招摇过市” 目前,我的解决方法是实现一个文档过滤器,它查找枚举并用枚举的内容填充相关描述
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.DocumentFilter<SwaggerAddEnumDescriptions>();
//disable this
//c.DescribeAllEnumsAsStrings()
GlobalConfiguration.Configuration
.EnableSwagger(c=>
{
c、 DocumentFilter();
//禁用此
//c、 descripbeAllenumsasstrings()
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());
}
}
使用系统;
使用System.Web.Http.Description;
使用虚张声势的皮带扣。虚张声势;
使用System.Collections.Generic;
公共类SwaggerAddEnumDescriptions:IDocumentFilter
{
public void Apply(swagger文档swagger文档、SchemaRegistry SchemaRegistry、IApiExplorer apiExplorer)
{
//将枚举描述添加到结果模型
foreach(swaggerDoc.definitions中的KeyValuePair schemaDictionaryItem)
{
Schema=schemaDictionaryItem.Value;
foreach(schema.properties中的KeyValuePair propertyDictionaryItem)
{
Schema属性=propertyDictionaryItem.Value;
IList propertyEnums=属性。@枚举;
如果(propertyEnums!=null&&propertyEnums.Count>0)
{
property.description+=descripbeenum(propertyEnums);
}
}
}
//将枚举描述添加到输入参数
如果(swaggerDoc.path.Count>0)
{
foreach(swaggerDoc.path.Values中的PathItem-PathItem)
{
描述参数(路径项参数);
//标题、补丁、选项、删除遗漏
List possibleParameterisedOperations=新列表{pathItem.get、pathItem.post、pathItem.put};
FindAll(x=>x!=null).ForEach(x=>descripbeenumparameters(x.parameters));
}
}
}
私有void描述符参数(IList参数)
{
if(参数!=null)
{
foreach(参数中的参数param)
{
IList paramEnums=param@enum;
if(paramEnums!=null&¶mEnums.Count>0)
{
param.description+=descripbeenum(参数);
}
}
}
}
私有字符串DescribeEnum(IList枚举)
{
List enumDescriptions=新列表();
foreach(枚举中的对象枚举选项)
{
添加(string.Format(“{0}={1}”,(int)enumOption,Enum.GetName(enumOption.GetType(),enumOption));
}
返回字符串.Join(“,”,enumDescriptions.ToArray());
}
}
这会在您的招摇过市用户界面上产生如下结果,这样您至少可以“看到自己在做什么”:
我想在.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
services.AddSwaggerGen(c => {
c.DescribeAllEnumsAsStrings();
});
Model.cs
public enum ColumnType {
DATE = 0
}
swagger.json
type: {
enum: ["DATE"],
type: "string"
}
我希望这能帮助您了解它对我的帮助!在Startup.cs中编写代码
services.AddSwaggerGen(c => {
c.DescribeAllEnumsAsStrings();
});
对于带有Microsoft JSON库(System.Text.JSON)的ASP.NET Core 3
在Startup.cs/ConfigureServices()中:
对于带有Json.NET(Newtonsoft.Json)库的ASP.NET Core 3
安装swashback.AspNetCore.Newtonsoft
软件包
在Startup.cs/ConfigureServices()中:
对于ASP.NET核心2
在Startup.cs/ConfigureServices()中:
ASP.NET前内核
httpConfiguration
.EnableSwagger(c=>
{
c、 descripbeAllenumsasstrings();
});
.Net核心3.0
using Newtonsoft.Json.Converters;
services
.AddMvc(options =>
{
options.EnableEndpointRouting = false;
})
.AddNewtonsoftJson(options => options.SerializerSettings.Converters.Add(new StringEnumConverter()))
使用asp.net核心3
using System.Text.Json.Serialization;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
但是Swashback版本5.0.0-rc4似乎还没有准备好支持它,所以我们需要在Swashback配置文件中使用一个选项(不推荐),直到它像Newtonsoft库一样支持和反映它
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
c.DescribeAllEnumsAsStrings();
此答案与其他答案的区别在于仅使用Microsoft JSON库而不是Newtonsoft。ASP NET解决方案 在我的api文档中,一个枚举仍然显示为int,尽管属性被标记为
StringEnumConverter
。我们无法为上面提到的所有枚举使用全局设置。在SwaggerConfig中添加此行解决了此问题:
c.MapType<ContactInfoType>(() => new Schema { type = "string", @enum = Enum.GetNames(typeof(ContactInfoType))});
c.MapType(()=>newsche
services
.AddControllersWithViews(...)
.AddNewtonsoftJson(options =>
options.SerializerSettings.Converters.Add(new StringEnumConverter()));
// order is vital, this *must* be called *after* AddNewtonsoftJson()
services.AddSwaggerGenNewtonsoftSupport();
services
.AddMvc(...)
.AddJsonOptions(options =>
options.SerializerSettings.Converters.Add(new StringEnumConverter()));
using Newtonsoft.Json.Converters;
services
.AddMvc(options =>
{
options.EnableEndpointRouting = false;
})
.AddNewtonsoftJson(options => options.SerializerSettings.Converters.Add(new StringEnumConverter()))
using System.Text.Json.Serialization;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
c.DescribeAllEnumsAsStrings();
c.MapType<ContactInfoType>(() => new Schema { type = "string", @enum = Enum.GetNames(typeof(ContactInfoType))});
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 (OpenApiInteger enumOption in enums)
{
int enumInt = enumOption.Value;
enumDescriptions.Add(string.Format("{0} = {1}", enumInt, Enum.GetName(enumType, enumInt)));
}
return string.Join(", ", enumDescriptions.ToArray());
}
}
services.AddMvc()
...
.AddNewtonsoftJson(opts =>
{
opts.SerializerSettings.Converters.Add(new StringEnumConverter());
});
services.AddSwaggerGen(...);
services.AddSwaggerGenNewtonsoftSupport(); //
[DataContract]
public class enum Colors
{
[EnumMember(Value="brightPink")]
BrightPink,
[EnumMember(Value="blue")]
Blue
}
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));
}
}
}
}
}
services.AddControllers()
.AddJsonOptions(opt => opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverterWithAttributeSupport()));
services.AddSwaggerGen(c => {
c.SchemaFilter<DescribeEnumMemberValues>();
});
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)));
}
}
}
}
services.AddSwaggerGen(options =>
{
options.SchemaFilter<EnumSchemaFilter>();
}
using System.Text.Json.Serialization;
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum MyEnum
{
A, B
}
using System.Linq;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace WebFramework.Swagger
{
public class EnumSchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (context.Type.IsEnum)
{
var enumValues = schema.Enum.ToArray();
var i = 0;
schema.Enum.Clear();
foreach (var n in Enum.GetNames(context.Type).ToList())
{
schema.Enum.Add(new OpenApiString(n + $" = {((OpenApiPrimitive<int>)enumValues[i]).Value}"));
i++;
}
}
}
}
}
services.AddSwaggerGen(options =>
{
#region EnumDesc
options.SchemaFilter<EnumSchemaFilter>();
#endregion
});
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());
}
}
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "web server api", Version = "v1" });
c.SchemaFilter<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}")));
}
}
}
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>();
});
using Newtonsoft.Json.Converters;
[JsonConverter(typeof(StringEnumConverter))]
public enum MyEnum
{
A, B
}
using System.Text.Json.Serialization;
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum MyEnum
{
A, B
}
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
services.AddControllers(options =>
{
options.ReturnHttpNotAcceptable = true;
var builder = new AuthorizationPolicyBuilder().RequireAuthenticatedUser();
options.Filters.Add(new AuthorizeFilter(builder.Build()));
}).AddJsonOptions(options =>
{
options.JsonSerializerOptions.IgnoreNullValues = true;
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
using System.Text.Json.Serialization;
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum Priority
{
Low,
Medium,
High
}