在 Swagger 下拉菜单和 json 上显示枚举成员友好名称
Show Enum member friendly name on Swagger dropdown and json
我正在尝试让枚举在响应时大摇大摆地显示描述(或任何其他属性)中的友好名称。还尝试解析控制器操作中 body/querystring 上设置的友好名称,而不尝试 400 BadRequest 或任何类型的验证错误。我还注意到,我拥有的自定义通用 JsonConverter 也无法正常工作。 ReadJson()
方法根本没有被调用。我怎样才能让它工作?
[JsonConverter(typeof(JsonEnumConverter<SortDirectionType>))]
public enum SortDirectionType
{
[Description("asc")]
ASCENDING,
[Description("desc")]
DESCENDING
}
我正在尝试让 swagger-ui 将 asc 和 desc 显示为下拉列表中的值,而不是 ASCENDING 和 DESCENDING。这意味着我不能使用 c.DescribeAllEnumsAsStrings()
。如果我不使用它,那么下拉列表会显示 0,1,因为它应该代表枚举成员值。现在我可以使用 [EnumMember(Value="asc"]
属性而不是 [Description("asc")]
属性。然而,随后发生了两件事:
- 要么 swagger-ui 抛出客户端验证并突出显示周围有红线的字段
- 或者如果我尝试在 swagger 之外调用端点 returns 400 错误。
- 我能够在操作
[FromBody]
参数中成功使用 0,1 或 ASCENDING、DESCENDING 值。然而,这不是预期的。我将接收 asc、desc,并希望能够在 body 模型上成功解析并将其映射到枚举 属性。另一方面,当 json 呈现时,它应该呈现友好名称。
附加代码:
public class JsonEnumConverter<T> : JsonConverter where T : struct, IComparable, IConvertible, IFormattable
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(T);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var type = typeof(T);
if (!type.IsEnum) throw new InvalidOperationException();
var enumDescription = (string)reader.Value;
return enumDescription.GetEnumValueFromDescription<T>();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var type = typeof(T);
if (!type.IsEnum) throw new InvalidOperationException();
if (value != null)
{
if (value is Enum sourceEnum)
{
writer.WriteValue(sourceEnum.GetDescriptionFromEnumValue());
}
}
}
}
public static class EnumExtensions
{
public static string GetDescriptionFromEnumValue(this Enum @enum)
{
FieldInfo fi = @enum.GetType().GetField(@enum.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute),
false);
if (attributes != null &&
attributes.Length > 0)
return attributes[0].Description;
else
return @enum.ToString();
}
public static T GetEnumValueFromDescription<T>(this string description)
{
var type = typeof(T);
if (!type.IsEnum)
throw new InvalidOperationException();
foreach (var field in type.GetFields())
{
if (Attribute.GetCustomAttribute(field,
typeof(DescriptionAttribute)) is DescriptionAttribute attribute)
{
if (attribute.Description == description)
return (T)field.GetValue(null);
}
else
{
if (field.Name == description)
return (T)field.GetValue(null);
}
}
throw new ArgumentException($"No matching value for enum {nameof(T)} found from {description}.",$"{nameof(description)}"); // or return default(T);
}
}
这就是为我做的:
services.AddSwaggerGen(c => {
c.DescribeAllEnumsAsStrings();
});
I found the it here
我想出了一个办法。它可能不一定是您的解决方案,但是如果您可以让它工作,那么我很高兴能提供帮助。
最终将枚举格式更改为字符串而不是默认下拉列表。这样我就可以将 asc/desc 值发送到 api。 Swagger 接受了这些值并且没有抛出验证错误。我在 .net core api 上编写的转换器也能够很好地转换它们。
c.MapType<SortDirectionType>(() => new Schema { Type = "string", Format = "string" });
除此之外,您可能还想禁用自动启动的 asp.net 核心 2.2 验证的默认行为。不确定他们为什么选择将其设置为默认行为。
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
我正在尝试让枚举在响应时大摇大摆地显示描述(或任何其他属性)中的友好名称。还尝试解析控制器操作中 body/querystring 上设置的友好名称,而不尝试 400 BadRequest 或任何类型的验证错误。我还注意到,我拥有的自定义通用 JsonConverter 也无法正常工作。 ReadJson()
方法根本没有被调用。我怎样才能让它工作?
[JsonConverter(typeof(JsonEnumConverter<SortDirectionType>))]
public enum SortDirectionType
{
[Description("asc")]
ASCENDING,
[Description("desc")]
DESCENDING
}
我正在尝试让 swagger-ui 将 asc 和 desc 显示为下拉列表中的值,而不是 ASCENDING 和 DESCENDING。这意味着我不能使用 c.DescribeAllEnumsAsStrings()
。如果我不使用它,那么下拉列表会显示 0,1,因为它应该代表枚举成员值。现在我可以使用 [EnumMember(Value="asc"]
属性而不是 [Description("asc")]
属性。然而,随后发生了两件事:
- 要么 swagger-ui 抛出客户端验证并突出显示周围有红线的字段
- 或者如果我尝试在 swagger 之外调用端点 returns 400 错误。
- 我能够在操作
[FromBody]
参数中成功使用 0,1 或 ASCENDING、DESCENDING 值。然而,这不是预期的。我将接收 asc、desc,并希望能够在 body 模型上成功解析并将其映射到枚举 属性。另一方面,当 json 呈现时,它应该呈现友好名称。
附加代码:
public class JsonEnumConverter<T> : JsonConverter where T : struct, IComparable, IConvertible, IFormattable
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(T);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var type = typeof(T);
if (!type.IsEnum) throw new InvalidOperationException();
var enumDescription = (string)reader.Value;
return enumDescription.GetEnumValueFromDescription<T>();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var type = typeof(T);
if (!type.IsEnum) throw new InvalidOperationException();
if (value != null)
{
if (value is Enum sourceEnum)
{
writer.WriteValue(sourceEnum.GetDescriptionFromEnumValue());
}
}
}
}
public static class EnumExtensions
{
public static string GetDescriptionFromEnumValue(this Enum @enum)
{
FieldInfo fi = @enum.GetType().GetField(@enum.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute),
false);
if (attributes != null &&
attributes.Length > 0)
return attributes[0].Description;
else
return @enum.ToString();
}
public static T GetEnumValueFromDescription<T>(this string description)
{
var type = typeof(T);
if (!type.IsEnum)
throw new InvalidOperationException();
foreach (var field in type.GetFields())
{
if (Attribute.GetCustomAttribute(field,
typeof(DescriptionAttribute)) is DescriptionAttribute attribute)
{
if (attribute.Description == description)
return (T)field.GetValue(null);
}
else
{
if (field.Name == description)
return (T)field.GetValue(null);
}
}
throw new ArgumentException($"No matching value for enum {nameof(T)} found from {description}.",$"{nameof(description)}"); // or return default(T);
}
}
这就是为我做的:
services.AddSwaggerGen(c => {
c.DescribeAllEnumsAsStrings();
});
I found the it here
我想出了一个办法。它可能不一定是您的解决方案,但是如果您可以让它工作,那么我很高兴能提供帮助。
最终将枚举格式更改为字符串而不是默认下拉列表。这样我就可以将 asc/desc 值发送到 api。 Swagger 接受了这些值并且没有抛出验证错误。我在 .net core api 上编写的转换器也能够很好地转换它们。
c.MapType<SortDirectionType>(() => new Schema { Type = "string", Format = "string" });
除此之外,您可能还想禁用自动启动的 asp.net 核心 2.2 验证的默认行为。不确定他们为什么选择将其设置为默认行为。
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});