替 swagger 加上具有可讀性的 enum 文件

  • 297
  • 0
  • 2024-02-16

以往在 controller 裡使用了 enum 的參數,但在 swagger 中顯示的都很悲劇,導致使用端會不知道怎麼使用這個參數,或是這些值分別是代表什麼

 

 

以下面這個例子來看,Color 1, 3, 5 分別是代表什麼?

 

public enum Color
    {
        R = 1,
        G = 3, 
        B = 5
    };

    public class ColorModifyReq
    {
        public Color color { set; get; }
        public int userId { set; get; }
    }
    
    [ApiController]
    [Route("api/v1/[controller]")]
    public class UserController : ControllerBase
    {
        /// <summary>
        /// 替某個使用者設定顏色碼
        /// </summary>
        /// <param name="color"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPut("color")]
        [SwaggerRequestExample(typeof(ColorModifyReq), typeof(ColorModifyReqSample))]
        public IActionResult Color(ColorModifyReq req)
        {
            return Ok();
        }
    }
 public class ColorModifyReqSample : IExamplesProvider<ColorModifyReq>
    {
        public ColorModifyReq GetExamples()
        {
            return new ColorModifyReq
            {
                color = Color.R,
                userId =123
            };
        }
    }

swagger 是有方式可以解決這個問題的
需要先加上 filter 主要用來處理 enum 型別的問題

public class EnumSchemaFilter : ISchemaFilter
   {
       public void Apply(OpenApiSchema schema, SchemaFilterContext context)
       {
           if (context.Type.IsEnum)
           {
               schema.Enum.Clear();
               Enum.GetNames(context.Type)
                   .Select(e => new
                   {
                       DisplayString = e,
                       EnumValue = (int)Enum.Parse(context.Type, e)
                   })
                   .ToList()
                   .ForEach(name => schema.Enum.Add(new OpenApiString($"[{name.EnumValue}]:{name.DisplayString}")));
           }
       }
   }

最後在啟動時把這個 filter 掛上來就好了

builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "demo", Version = "v1" });
    c.ExampleFilters();
    c.SchemaFilter<EnumSchemaFilter>();

    // Set the comments path for the Swagger JSON and UI.
    List<string> xmlFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.xml", SearchOption.TopDirectoryOnly).ToList();
    xmlFiles.ForEach(xmlFile => c.IncludeXmlComments(xmlFile));
    c.CustomSchemaIds(x => x.FullName);
});

接著來看看結果

收到資料也是正常的

參考資料: https://thomasdewulf.dev/posts/enums-net6-openapi/