193

すべての列挙型を int 値ではなく文字列値として表示する方法はありますか?

POST アクションを送信し、その文字列の値に応じて列挙型を配置できるようにしたいのですが、毎回列挙型を確認する必要はありません。

試してみ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
}
4

24 に答える 24

253

グローバルに有効にする

ドキュメントから:

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

Newtonsoft および Swashbuckle v5.0.0 以降を使用している場合

次のパッケージも必要です。

Swashbuckle.AspNetCore.Newtonsoft

そして、これはあなたのスタートアップで:

services.AddSwaggerGenNewtonsoftSupport(); // explicit opt-in - needs to be placed after AddSwaggerGen()

ここにドキュメントがあります: https://github.com/domaindrivendev/Swashbuckle.AspNetCore#systemtextjson-stj-vs-newtonsoft

于 2016-06-06T13:26:11.227 に答える
21

誰かが興味を持っているなら、私は動作するようにコードを修正しました

.NET CORE 3Swagger V5

    public class SwaggerAddEnumDescriptions : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        // add enum descriptions to result models
        foreach (var property in swaggerDoc.Components.Schemas.Where(x => x.Value?.Enum?.Count > 0))
        {
            IList<IOpenApiAny> propertyEnums = property.Value.Enum;
            if (propertyEnums != null && propertyEnums.Count > 0)
            {
                property.Value.Description += DescribeEnum(propertyEnums, property.Key);
            }
        }

        // add enum descriptions to input parameters
        foreach (var pathItem in swaggerDoc.Paths.Values)
        {
            DescribeEnumParameters(pathItem.Operations, swaggerDoc);
        }
    }

    private void DescribeEnumParameters(IDictionary<OperationType, OpenApiOperation> operations, OpenApiDocument swaggerDoc)
    {
        if (operations != null)
        {
            foreach (var oper in operations)
            {
                foreach (var param in oper.Value.Parameters)
                {
                    var paramEnum = swaggerDoc.Components.Schemas.FirstOrDefault(x => x.Key == param.Name);
                    if (paramEnum.Value != null)
                    {
                        param.Description += DescribeEnum(paramEnum.Value.Enum, paramEnum.Key);
                    }
                }
            }
        }
    }

    private Type GetEnumTypeByName(string enumTypeName)
    {
        return AppDomain.CurrentDomain
            .GetAssemblies()
            .SelectMany(x => x.GetTypes())
            .FirstOrDefault(x => x.Name == enumTypeName);
    }

    private string DescribeEnum(IList<IOpenApiAny> enums, string proprtyTypeName)
    {
        List<string> enumDescriptions = new List<string>();
        var enumType = GetEnumTypeByName(proprtyTypeName);
        if (enumType == null)
            return null;

        foreach (IOpenApiAny enumOption in enums)
        {
            if (enumOption is OpenApiString @string)
            {
                string enumString = @string.Value;

                enumDescriptions.Add(string.Format("{0} = {1}", (int)Enum.Parse(enumType, enumString), enumString));
            }
            else if (enumOption is OpenApiInteger integer)
            {
                int enumInt = integer.Value;

                enumDescriptions.Add(string.Format("{0} = {1}", enumInt, Enum.GetName(enumType, enumInt)));
            }
        }

        return string.Join(", ", enumDescriptions.ToArray());
    }
}
于 2019-12-25T12:09:58.220 に答える
14

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 ライブラリのみを使用していることです。

于 2019-10-17T08:37:44.933 に答える
2

swagger のバージョンが 5.5.x の場合は、次のことを行う必要があります。

  1. インストール: インストール パッケージ Swashbuckle.AspNetCore.Newtonsoft -バージョン 5.5.0

  2. services.AddSwaggerGenNewtonsoftSupport();

参照: https://github.com/domaindrivendev/Swashbuckle.AspNetCore#systemtextjson-stj-vs-newtonsoft

于 2020-08-02T07:50:06.850 に答える
1

列挙型を swagger の文字列として表示するには、 JsonStringEnumConverter を構成し、 ConfigureServices に次の行を追加します。

services.AddControllers().AddJsonOptions(options =>
            options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));

列挙型を文字列および int 値として表示する場合は、EnumSchemaFilter を作成してスキーマを変更してみてください。以下のようなコード:

public class EnumSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema model, SchemaFilterContext context)
    {
        if (context.Type.IsEnum)
        {
            model.Enum.Clear();
            Enum.GetNames(context.Type)
                .ToList()
                .ForEach(name => model.Enum.Add(new OpenApiString($"{Convert.ToInt64(Enum.Parse(context.Type, name))} = {name}")));
        }
    }
}

上記の ShemaFilter を使用するように SwaggerGen を構成します。

services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo
            {
                Version = "v1",
                Title = "ToDo API",
                Description = "A simple example ASP.NET Core Web API",
                TermsOfService = new Uri("https://example.com/terms"),
                Contact = new OpenApiContact
                {
                    Name = "Shayne Boyer",
                    Email = string.Empty,
                    Url = new Uri("https://twitter.com/spboyer"),
                },
                License = new OpenApiLicense
                {
                    Name = "Use under LICX",
                    Url = new Uri("https://example.com/license"),
                }
            });
              
            c.SchemaFilter<EnumSchemaFilter>();
        });
于 2021-11-29T10:57:25.013 に答える
1

私たちが探していたものに対する他の回答で見つけた多くの欠点があったので、私はこれについて私自身の見解を提供すると思いました. ASP.NET Core 3.1 と System.Text.Json を使用していますが、このアプローチは使用する JSON シリアライザーに関係なく機能します。

私たちの目標は、ASP.NET Core API の両方で小文字のキャメル ケースの列挙型文字列値を受け入れ、Swagger で同じことを文書化することでした。現在、 と を使用している[DataContract]ため[EnumMember]、EnumMember 値プロパティからキャメルケースの値を小文字にして、それを全面的に使用するというアプローチです。

サンプルの列挙型:

[DataContract]
public class enum Colors
{
  [EnumMember(Value="brightPink")]
  BrightPink,
  [EnumMember(Value="blue")]
  Blue
}

次のように ISchemaFilter を使用して、Swashbuckle で EnumMember 値を使用します。

public class DescribeEnumMemberValues : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (context.Type.IsEnum)
        {
            schema.Enum.Clear();

            //Retrieve each of the values decorated with an EnumMember attribute
            foreach (var member in context.Type.GetMembers())
            {
                var memberAttr = member.GetCustomAttributes(typeof(EnumMemberAttribute), false).FirstOrDefault();
                if (memberAttr != null)
                {
                    var attr = (EnumMemberAttribute) memberAttr;
                    schema.Enum.Add(new OpenApiString(attr.Value));
                }
            }
        }
    }
}

サード パーティの NuGet パッケージ(GitHubリポジトリ) を使用して、この命名規則が ASP.NET Core でも利用されるようにしています。次のように、ConfigureServices 内の Startup.cs で構成します。

services.AddControllers()
  .AddJsonOptions(opt => opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverterWithAttributeSupport()));

最後に、ISchemaFilter を Swashbuckle に登録する必要があるため、ConfigureServices() にも以下を追加します。

services.AddSwaggerGen(c => {
  c.SchemaFilter<DescribeEnumMemberValues>();
});
于 2020-01-25T18:50:36.687 に答える