【问题标题】:Autorest + Swagger does not generate ENUMs properlyAutorest + Swagger 无法正确生成 ENUM
【发布时间】:2018-02-24 12:29:22
【问题描述】:

我有两个应用程序 A 和 B。在 A 上,我使用 swagger 来描述 API。在 A 上,我还定义了具有一些枚举属性的类。 我想在 B 上生成客户端 API。为此,我使用 Autorest。一切都很好,除了一件事 - 枚举。由于某种原因,枚举没有正确生成,并且属性类型(最初是枚举)是字符串类型或 int 类型(取决于 DescribeAllEnumsAsStrings() 的使用。我在下面的示例中使用它所以在这种情况下它是字符串)。

Enum 定义 swagger 生成 JSON:

        "Car": {
        "properties": {
            "color": {
                "enum": [
                    "Red",
                    "Blue",
                    "Green"
                ],
                "type": "string"
            }
        },
        "type": "object"
    }

Startup.cs 中的 Swagger 注册

// Register the Swagger generator, defining one or more Swagger documents
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info { Title = "Car API", Version = "v1" });
            c.AddSecurityDefinition("Bearer", new ApiKeyScheme { In = "header", Description = "description", Name = "Authorization", Type = "apiKey" });
            c.DescribeAllEnumsAsStrings();
        });

自动休息命令:

autorest --input-file=http://localhost:55448/swagger/v1/swagger.json --csharp --namespace=Online.Integrations.Api.Service.Car --output-folder=. 

生成的类(字符串而不是枚举):

    public partial class Car
{
    /// <summary>
    /// Initializes a new instance of the Car class.
    /// </summary>
    public Car()
    {
      CustomInit();
    }

    /// <summary>
    /// Initializes a new instance of the Car class.
    /// </summary>
    /// <param name="application">Possible values include: 'Any', 'Web'
    /// ...
    /// </param>
    public Car(string color = default(string))
    {
        Color = color;
    }

    /// <summary>
    /// An initialization method that performs custom operations like setting defaults
    /// </summary>
    partial void CustomInit();

    /// <summary>
    /// </summary>
    [JsonProperty(PropertyName = "color")]
    public string Color { get; set; }
}

我发现了这个:https://github.com/Azure/autorest/tree/master/docs/extensions#x-ms-enum

有一些 x-ms-enum 扩展,但我不知道如何使用它。我尝试手动编辑 JSON 定义(我在下面的示例中所做的)但它也没有成功。生成的类包含 object color = default(object) 而不是第一个示例中的字符串,而不是枚举。

    "color": {
            "type": "string",
            "enum": [
                "Red",
                "Blue",
                "Green"
            ],
            "x-ms-enum": {
                "name": "Color",
                "modelAsString": false
     },

我会很高兴得到任何帮助。谢谢!

编辑: 1) 完整的 Swagger 定义(结果类型:Sting):

在大摇大摆的定义中。在枚举定义之后是 "type": "string"

 {"swagger":"2.0","info":{"version":"v1","title":"Audit Overseer API"},"basePath":"/","paths":{"/api/Audit":{"get":{"tags":["Audit"],"operationId":"ApiAuditGet","consumes":[],"produces":["text/plain","application/json","text/json"],"parameters":[{"name":"Id","in":"query","required":false,"type":"string"},{"name":"Application","in":"query","required":false,"type":"string","enum":["Any","Alfa","Beta"]},{"name":"DatabaseName","in":"query","required":false,"type":"string"}],"responses":{"200":{"description":"Success","schema":{"type":"array","items":{"$ref":"#/definitions/Transaction"}}}}}}},"definitions":{"Transaction":{"type":"object","properties":{"callId":{"type":"string"},"actionName":{"type":"string"},"application":{"enum":["Any","Alfa","Beta"],"type":"string"},"httpStatusCode":{"type":"string"},"dateTime":{"format":"date-time","type":"string"}}}},"securityDefinitions":{"Bearer":{"name":"Authorization","in":"header","type":"apiKey","description":"Please insert JWT with Bearer into field"}}}

自动执行:

结果:

2) 完整的 Swagger 定义(结果类型:对象):

在大摇大摆的定义中。我在枚举定义之后对“x-ms-enum”的实验

{"basePath":"/","definitions":{"Transaction":{"properties":{"actionName":{"type":"string"},"application":{"enum":["Any","Alfa","Beta"],"x-ms-enum":{"modelAsString":false,"name":"Application"}},"callId":{"type":"string"},"dateTime":{"format":"date-time","type":"string"},"httpStatusCode":{"type":"string"}},"type":"object"}},"info":{"title":"Audit Overseer API","version":"v1"},"paths":{"/api/Audit":{"get":{"consumes":[],"operationId":"ApiAuditGet","parameters":[{"in":"query","name":"Id","required":false,"type":"string"},{"enum":["Any","Alfa","Beta"],"in":"query","name":"Application","required":false,"type":"string"},{"in":"query","name":"DatabaseName","required":false,"type":"string"}],"produces":["text/plain","application/json","text/json"],"responses":{"200":{"description":"Success","schema":{"items":{"$ref":"#/definitions/Transaction"},"type":"array"}}},"tags":["Audit"]}}},"securityDefinitions":{"Bearer":{"description":"Please insert JWT with Bearer into field","in":"header","name":"Authorization","type":"apiKey"}},"swagger":"2.0"}

...或者我可以把它留空。结果是一样的

{"basePath":"/","definitions":{"Transaction":{"properties":{"actionName":{"type":"string"},"application":{"enum":["Any","Alfa","Beta"]},"callId":{"type":"string"},"dateTime":{"format":"date-time","type":"string"},"httpStatusCode":{"type":"string"}},"type":"object"}},"info":{"title":"Audit Overseer API","version":"v1"},"paths":{"/api/Audit":{"get":{"consumes":[],"operationId":"ApiAuditGet","parameters":[{"in":"query","name":"Id","required":false,"type":"string"},{"enum":["Any","Alfa","Beta"],"in":"query","name":"Application","required":false,"type":"string"},{"in":"query","name":"DatabaseName","required":false,"type":"string"}],"produces":["text/plain","application/json","text/json"],"responses":{"200":{"description":"Success","schema":{"items":{"$ref":"#/definitions/Transaction"},"type":"array"}}},"tags":["Audit"]}}},"securityDefinitions":{"Bearer":{"description":"Please insert JWT with Bearer into field","in":"header","name":"Authorization","type":"apiKey"}},"swagger":"2.0"}

(现在让我们执行与以前相同的 autorest 命令)

结果是:

【问题讨论】:

  • 您是否为此 API 指定了"consumes": ["application/json"]?如果未指定此类 consumes,则 AutoRest 的一个已知怪癖(为了向后兼容而保持不变)使其手指远离任何非内置/非原始类型。如果这没有帮助,请提供您的完整 Swagger,以便我可以重现。 :)
  • 您好,感谢您的回复。我尝试手动添加它,但它没有帮助。我对这个主题提出了完整的 Swagger json 定义。请看一下。感谢您的帮助!
  • 使用 x-ms-enum 对我来说是开箱即用的,就像你在上面粘贴的那样(我将它应用到 then 枚举 Any, Alfa, Beta)。发布您期望工作的 Swagger,但如果您需要进一步帮助,请联系 object。
  • "type": "string" 缺少属性 application - 添加后,它对我来说很好
  • 它有效。惊人的!有没有办法通过招摇自动生成值 x-ms-enum 值?或者我必须手动将它添加到json中?谢谢!

标签: c# asp.net-core swagger autorest


【解决方案1】:

您似乎可以使用SchemaFilter&lt;TFilter&gt; 选项方法让SwaggerGen 自动添加x-ms-enum 扩展。

Startup.cs 中的 Swagger 注册

// Register the Swagger generator, defining one or more Swagger documents
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info { Title = "Car API", Version = "v1" });
            c.AddSecurityDefinition("Bearer", new ApiKeyScheme { In = "header", Description = "description", Name = "Authorization", Type = "apiKey" });
            c.ApplyFiltersToAllSchemas();//ignore deprecation warning
            c.SchemaFilter<EnumFilter>();
            c.DescribeAllEnumsAsStrings();
        });

然后用下面的代码定义一个EnumFilter类

public class EnumFilter : ISchemaFilter
{
    public void Apply(Schema model, SchemaFilterContext context)
    {
        if (model == null)
            throw new ArgumentNullException("model");

        if (context == null)
            throw new ArgumentNullException("context");

        if (context.SystemType.IsEnum)
            model.Extensions.Add("x-ms-enum", new
            {
                name = context.SystemType.Name,
                modelAsString = false
            });
    }
}

【讨论】:

【解决方案2】:

寻找解决可为空的枚举的解决方案!

public class EnumFilter : ISchemaFilter
{

    public void Apply(Schema model, SchemaRegistry schemaRegistry, Type type)
    {
        if (model == null)
        {
            throw new ArgumentNullException("model");
        }

        if (schemaRegistry == null)
        {
            throw new ArgumentNullException("schemaRegistry");
        }

        if (IsEnum(type, out var enumName))
        {
            model.vendorExtensions.Add("x-ms-enum", new
                                              {
                                                  name = enumName ?? type.Name,
                                                  modelAsString = false
                                              });

        }
    }

    public static bool IsEnum(Type t, out string enumName)
    {
        if (t.IsEnum)
        {
            enumName = t.Name;
            return true;
        }
        Type u = Nullable.GetUnderlyingType(t);
        enumName = u?.Name;
        return (u != null) && u.IsEnum;
    }
}

【讨论】:

【解决方案3】:

面向未来的解决方案,在@richard-mcdaniel 解决方案的基础上,一旦出色的enum values issue on the autorest repo 得到修复,这里是EnumFilter:ISchemaFilter 的枚举部分的值

Startup.cs 中的 Swagger 注册

// Register the Swagger generator, defining one or more Swagger documents
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info { Title = "Car API", Version = "v1" });
            c.AddSecurityDefinition("Bearer", new ApiKeyScheme { In = "header", Description = "description", Name = "Authorization", Type = "apiKey" });
            c.ApplyFiltersToAllSchemas();//ignore deprecation warning
            c.SchemaFilter(() => new EnumTypeSchemaFilter(false));
            c.DescribeAllEnumsAsStrings();
        });

然后用下面的代码定义一个EnumFilter类:

using Swashbuckle.Swagger;
using System;

namespace Swashbuckle.AutoRestExtensions
{
    public class EnumTypeSchemaFilter : ISchemaFilter
    {
        public EnumTypeSchemaFilter()
        {
        }

        public EnumTypeSchemaFilter(bool modelAsString)
        {
            _modelAsString = modelAsString;
        }

        public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
        {
            type = Nullable.GetUnderlyingType(type) ?? type;
            System.Diagnostics.Debug.WriteLine(type.FullName);
            if (type.IsEnum)
            {
                // Add enum type information once
                if (schema.vendorExtensions.ContainsKey("x-ms-enum")) return;

                if (_modelAsString)
                {
                    schema.vendorExtensions.Add("x-ms-enum", new
                    {
                        name = type.Name,
                        modelAsString = _modelAsString
                    });
                }
                else
                {
                    var valuesList = new System.Collections.Generic.List<object>();
                    foreach (var fieldInfo in type.GetFields())
                    {
                        if (fieldInfo.FieldType.IsEnum)
                        {
                            var fName = fieldInfo.Name;
                            var fValue = (int)fieldInfo.GetRawConstantValue();
                            valuesList.Add(new { value = fValue, description = fName, name = fName });
                        }
                    }
                    schema.vendorExtensions.Add("x-ms-enum", new
                    {
                        name = type.Name,
                        modelAsString = _modelAsString,
                        values = valuesList
                        //Values:
                        /*
                        accountType:
                          type: string
                          enum:
                          - Standard_LRS
                          - Standard_ZRS
                          - Standard_GRS
                          - Standard_RAGRS
                          - Premium_LRS
                          x-ms-enum:
                            name: AccountType
                            modelAsString: false
                            values:
                            - value: Standard_LRS
                              description: Locally redundant storage.
                              name: StandardLocalRedundancy
                            - value: Standard_ZRS
                              description: Zone-redundant storage.
                            - value: Standard_GRS
                              name: StandardGeoRedundancy
                            - value: Standard_RAGRS
                            - value: Premium_LRS
                        */
                    });
                }
            }
        }

        private readonly bool _modelAsString;
    }
}

【讨论】:

    猜你喜欢
    • 2016-09-20
    • 2022-10-24
    • 2022-01-22
    • 2017-01-31
    • 1970-01-01
    • 2020-06-11
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    相关资源
    最近更新 更多