簡體   English   中英

在 Swagger 下拉列表和 json 上顯示 Enum 成員友好名稱

[英]Show Enum member friendly name on Swagger dropdown and json

我試圖讓枚舉在 swagger 和響應中顯示來自描述(或任何其他屬性)的友好名稱。 還嘗試解析控制器操作中正文/查詢字符串上設置的友好名稱,而不嘗試 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")]屬性。但是接下來發生了兩件事:

  1. 要么 swagger-ui 拋出客戶端驗證並用紅線突出顯示該字段
  2. 或者,如果我嘗試在 swagger 之外調用端點,它會返回 400 錯誤。
  3. 我可以在 action [FromBody]參數中成功使用 0,1 或 ASCENDING、DESCENDING 值。 然而,這不是預期的。 我將接收 asc、desc 並希望能夠在 body 模型上成功解析它並將其映射到 enum 屬性。 另一方面,當 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);
    }
}

https://github.com/domaindrivendev/Swashbuckle/issues/1318

這就是為我所做的:

  services.AddSwaggerGen(c => {
  c.DescribeAllEnumsAsStrings();
});

我在這里找到了

我想出了一個黑客在這里。 它可能不一定是您的解決方案,但是如果您可以使它工作,那么我很高興我可以提供幫助。

最終將枚舉格式更改為字符串而不是默認下拉列表。 這樣我就可以將 asc/desc 值發送到 api。 Swagger 接受了這些值並且沒有拋出驗證錯誤。 我在 .net core api 上編寫的轉換器也能夠很好地轉換它們。

c.MapType<SortDirectionType>(() => new Schema { Type = "string", Format = "string" });

除此之外,您可能還想禁用自動啟動的 asp.net core 2.2 驗證的默認行為。 不知道他們為什么選擇將其設置為默認行為。

services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressModelStateInvalidFilter = true;
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM