[c#] Swagger UI Web Api 문서 열거 형을 문자열로 표시합니까?

모든 enum을 int 값 대신 swagger의 문자열 값으로 표시하는 방법이 있습니까?

매번 enum을 보지 않고도 POST 작업을 제출하고 문자열 값에 따라 enum을 넣을 수 있기를 원합니다.

시도 DescribeAllEnumsAsStrings했지만 서버는 우리가 찾고있는 것이 아닌 열거 형 값 대신 문자열을받습니다.

누구든지 이것을 해결 했습니까?

편집하다:

public class Letter
{
    [Required]
    public string Content {get; set;}

    [Required]
    [EnumDataType(typeof(Priority))]
    public Priority Priority {get; set;}
}


public class LettersController : ApiController
{
    [HttpPost]
    public IHttpActionResult SendLetter(Letter letter)
    {
        // Validation not passing when using DescribeEnumsAsStrings
        if (!ModelState.IsValid)
            return BadRequest("Not valid")

        ..
    }

    // In the documentation for this request I want to see the string values of the enum before submitting: Low, Medium, High. Instead of 0, 1, 2
    [HttpGet]
    public IHttpActionResult GetByPriority (Priority priority)
    {

    }
}


public enum Priority
{
    Low,
    Medium,
    High
}



답변

에서 워드 프로세서 :

httpConfiguration
    .EnableSwagger(c =>
        {
            c.SingleApiVersion("v1", "A title for your API");

            c.DescribeAllEnumsAsStrings(); // this will do the trick
        });

또한 특정 유형 및 속성에서만이 동작을 원하면 StringEnumConverter를 사용합니다.

public class Letter
{
    [Required]
    public string Content {get; set;}

    [Required]
    [EnumDataType(typeof(Priority))]
    [JsonConverter(typeof(StringEnumConverter))]
    public Priority Priority {get; set;}
}


답변

Microsoft JSON 라이브러리 (System.Text.Json)가있는 ASP.NET Core 3의 경우

Startup.cs / ConfigureServices ()에서 :

services
    .AddControllersWithViews(...) // or AddControllers() in a Web API
    .AddJsonOptions(options =>
        options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));

Json.NET (Newtonsoft.Json) 라이브러리가있는 ASP.NET Core 3의 경우

Swashbuckle.AspNetCore.Newtonsoft패키지를 설치하십시오 .

Startup.cs / ConfigureServices ()에서 :

services
    .AddControllersWithViews(...)
    .AddNewtonsoftJson(options =>
        options.SerializerSettings.Converters.Add(new StringEnumConverter()));
// order is vital, this *must* be called *after* AddNewtonsoftJson()
services.AddSwaggerGenNewtonsoftSupport();

ASP.NET Core 2의 경우

Startup.cs / ConfigureServices ()에서 :

services
    .AddMvc(...)
    .AddJsonOptions(options =>
        options.SerializerSettings.Converters.Add(new StringEnumConverter()));

ASP.NET Core 이전

httpConfiguration
    .EnableSwagger(c =>
        {
            c.DescribeAllEnumsAsStrings();
        });


답변

그래서 비슷한 문제가 있다고 생각합니다. int-> string mapping과 함께 enum을 생성하기 위해 swagger를 찾고 있습니다. API는 int를 허용해야합니다. swagger-ui는 덜 중요합니다. 제가 정말로 원하는 것은 다른쪽에 “실제”열거 형 (이 경우 개조를 사용하는 안드로이드 앱)을 사용하여 코드를 생성하는 것입니다.

그래서 내 연구에서 이것은 궁극적으로 Swagger가 사용하는 OpenAPI 사양의 한계 인 것 같습니다. 열거 형에 이름과 숫자를 지정할 수 없습니다.

내가 찾은 가장 좋은 문제는 https://github.com/OAI/OpenAPI-Specification/issues/681 입니다. “아마 곧”처럼 보이지만 Swagger를 업데이트해야하며 제 경우에는 Swashbuckle이 잘.

현재 내 해결 방법은 열거 형을 찾고 관련 설명을 열거 형의 내용으로 채우는 문서 필터를 구현하는 것입니다.

        GlobalConfiguration.Configuration
            .EnableSwagger(c =>
                {
                    c.DocumentFilter<SwaggerAddEnumDescriptions>();

                    //disable this
                    //c.DescribeAllEnumsAsStrings()

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());
    }

}

이렇게하면 swagger-ui에 다음과 같은 결과가 나타나므로 최소한 “당신이하는 일을 볼 수 있습니다”.
여기에 이미지 설명 입력


답변

ASP.NET Core 3.1

Newtonsoft JSON을 사용하여 열거 형을 문자열로 생성하려면 AddSwaggerGenNewtonsoftSupport()다음과 같이 추가하여 Newtonsoft 지원을 명시 적으로 추가해야 합니다.

services.AddMvc()
    ...
    .AddNewtonsoftJson(opts =>
    {
        opts.SerializerSettings.Converters.Add(new StringEnumConverter());
    });


services.AddSwaggerGen(...);
services.AddSwaggerGenNewtonsoftSupport(); //

이는 새 패키지 인 Swashbuckle.AspNetCore.Newtonsoft. 열거 형 변환기 지원을 제외하고이 패키지 없이는 다른 모든 것이 잘 작동하는 것 같습니다.


답변

.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)}";
    }
}

그런 다음 ConfigureServicesStartup.cs 의 메서드에 다음을 추가합니다 .

c.DocumentFilter<EnumDocumentFilter>();


답변

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()));

그러나 Swashbuckle 버전 5.0.0-rc4는이를 지원할 준비가되지 않은 것 같습니다. 따라서 Newtonsoft 라이브러리처럼 지원하고 반영 할 때까지 Swashbuckle 구성 파일에서 옵션 (사용되지 않음)을 사용해야합니다.

public void ConfigureServices(IServiceCollection services)
{
      services.AddSwaggerGen(c =>
      {
            c.DescribeAllEnumsAsStrings();

이 답변과 다른 답변의 차이점은 Newtonsoft 대신 Microsoft JSON 라이브러리 만 사용한다는 것입니다.


답변

.NET CORE 3.1 및 SWAGGER 5

열거 형 을 선택적 으로 문자열로 전달 하는 간단한 솔루션이 필요한 경우 :

using System.Text.Json.Serialization;


[JsonConverter(typeof(JsonStringEnumConverter))]
public enum MyEnum
{
    A, B
}

참고로, 우리 System.Text.Json.SerializationNewtonsoft.Json!