Swashbuckle -在swagger文档中将字符串视为枚举

9q78igpj  于 2023-11-18  发布在  其他
关注(0)|答案(3)|浏览(144)

我正在使用FluentValidation,我希望只从fluent验证器接收我的自定义错误。这就是为什么我在requests类中的所有属性都是字符串。然而,我还希望有更好的enum类型文档。
以下是我的示例请求:

public class AddNewPaymentRequest
 {
     [EnumDataType(typeof(PaymentStatus))]
     public string PaymentStatus { get; set; }

     public string Id { get; set; }
 }

字符串
和示例枚举:

public enum PaymentStatus
 {
     Unknown,
     New,
     Pending,
     Completed
 }


和控制器:

[HttpPost]
public async Task<ActionResult> PostAsync([FromBody] AddNewPaymentRequest request)
{
   ...
}


我想让这个EnumDataType作为Swagger显示枚举描述的信息,而不是字符串描述。我想让Swagger把这个字符串当作枚举。
实际结果:click
预期结果:click
有没有可能以这种方式配置Swashbuckle?

t40tm48m

t40tm48m1#

我想我们正在谈论.NET Core
如果你觉得可以的话,可以将其明确定义为枚举而不是字符串

public class AddNewPaymentRequest
 {
     //[EnumDataType(typeof(PaymentStatus))]
     //public string PaymentStatus { get; set; }

     public PaymentStatus PaymentStatus { get; set; }

     public string Id { get; set; }
 }

字符串
然后您可以定义SwaggerGen如何处理枚举

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


如果你在API上接收/发送数据时遇到了序列化/非序列化枚举的问题(通过Newtonsoft.Json),你可以对转换采取更多的控制器(如果必要)

[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
 public enum PaymentStatus
 {
     [EnumMember(Value = "Unknwon")]
     Unknown,

     [EnumMember(Value = "New")]
     New,

     [EnumMember(Value = "Pending")]
     Pending,

     [EnumMember(Value = "Completed")]
     Completed,

     [EnumMember(Value = "something_different_with_underline")]
     SomethingDifferentWithUnderline
 }


请注意,这些枚举的ToString()可能会导致不同的字符串(带/不带下划线)

jogvjijk

jogvjijk2#

Swaggers只支持RequiredAttributeObsoleteAttributeMetaData(外部类)。所以除了写这样的东西之外,没有办法描述接受的值:
/// <summary> Allowed values are....

oaxa6hgo

oaxa6hgo3#

这些答案都有效地说:“你不能这样做,这里有其他的选择。”好吧,你可以这样做,这里是如何。
创建一个名为OpenApiEnumAttribute的属性如下:

/// <summary>
/// Used in conjunction with OpenApiEnumSchemaFilter to apply the enum property
/// to an OpenAPI schema.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class OpenApiEnumAttribute : Attribute
{
    public OpenApiEnumAttribute(params string[] enumOptions)
    {
        EnumOptions = enumOptions;
    }
    
    public OpenApiEnumAttribute(Type enoom)
    {
        if (!enoom.IsEnum)
        {
            throw new ArgumentException("Type not an enum", nameof(enoom));
        }
        EnumOptions = Enum.GetNames(enoom);
    }
    
    /// <summary>
    /// Options for values that the property can have
    /// </summary>
    public string[] EnumOptions { get; }
}

字符串
然后创建一个Schema Filter,如下所示:

using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

/// <summary>
/// Applies the enum property to an OpenAPI schema. Most useful to constrain
/// strings to be a specific value.
/// </summary>
public class OpenApiEnumSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (context.MemberInfo == null)
        {
            return;
        }
        var enumAnnotation = context.MemberInfo.GetCustomAttributes(typeof(OpenApiEnumAttribute), false)
            .Cast<OpenApiEnumAttribute>()
            .FirstOrDefault();

        if (enumAnnotation == null) return;

        schema.Enum = enumAnnotation.EnumOptions.Select(option => new OpenApiString(option))
            .Cast<IOpenApiAny>().ToList();
    }
}


最后,在Startup.cs中(或者在任何地方调用AddSwaggerGen

services.AddSwaggerGen(config => { config.SchemaFilter<OpenApiEnumSchemaFilter>(); } );


根据你的例子,你现在可以这样使用它:

public class AddNewPaymentRequest
{
    [OpenApiEnum(typeof(PaymentStatus))]
    public string PaymentStatus { get; set; }

    public string Id { get; set; }
}

相关问题