2017-04-17 63 views
1

我正在與下列數據契約的一個更復雜的版本工作,但是這應足以作爲一個例子:生成swagger文件時如何讓Swashbuckle尊重DataType?

using System; 
using System.Runtime.Serialization; 
using System.ComponentModel; 
using System.ComponentModel.DataAnnotations; 

[DataContract(Namespace = "https://schemas.company.name/api-name/")] 
public class Subscription 
{ 
    [DataMember(IsRequired = true)] 
    public long SubscriptionID { get; set; } 

    [DataMember(IsRequired = true)] 
    public long ProductID { get; set; } 

    [DataMember(IsRequired = true)] 
    public long AccountID { get; set; } 

    [DataMember(IsRequired = true), DataType(DataType.Date)] 
    public DateTime StartDate { get; set; } 

    [DataMember(IsRequired = true), DataType(DataType.Date)] 
    public DateTime EndDate { get; set; } 
} 

通過Swashbuckle用於上述數據合同生成的招搖JSON定義變成這樣:

... 
    "Subscription": { 
     "required": ["subscriptionID", "productID", "accountID", "startDate", "endDate"], 
     "type": "object", 
     "properties": { 
      "subscriptionID": { 
       "format": "int64", 
       "type": "integer" 
      }, 
      "productID": { 
       "format": "int64", 
       "type": "integer" 
      }, 
      "accountID": { 
       "format": "int64", 
       "type": "integer" 
      }, 
      "startDate": { 
       "format": "date-time", 
       "type": "string" 
      }, 
      "endDate": { 
       "format": "date-time", 
       "type": "string" 
      } 
     } 
    }, 
... 

但是,你會發現JSON definitions.Subscription.properties.startDate.format"date-time",但DateTypeAttribute註釋在C#代碼DataType.Date,不DataType.DateTime

在生成swagger文件時,如何使Swashbuckle尊重System.ComponentModel.DataAnnotations.DataTypeAttribute?或者更具體地說,使用[DataType(DataType.Date]註釋的類屬性生成format"date"

我希望有這是所有類的默認行爲,因爲我有太多具體的類屬性的硬編碼的詳細信息,並使用Swashbuckle基礎上從內同其他註釋產生招搖JSON整點命名空間(如System.ComponentModel.DataAnnotations.StringLengthAttribute)。

我最初的嘗試是在我Startup.cs使用ISchemaFilter,如嘗試:

services.AddSwaggerGen(options => 
    { 
     ... 
     options.SchemaFilter<DataTypeSchemaFilter>(); 
     ... 
    }); 

如果實施過濾器類應用:

public class DataTypeSchemaFilter : ISchemaFilter 
{ 
    public void Apply(Schema model, SchemaFilterContext context) 
    { 
     ??? 
    } 
} 

不過,我看不出有什麼能力使用提供的Schema modelSchemaFilterContext context參數從過濾器內調查類屬性屬性。

如前所述,我知道Swashbuckle在處理類屬性時會查看同一名稱空間中的屬性,所以我希望有人知道我可以在哪裏綁定Swashbuckle並執行類似的任務。

回答

1

我已經寫下面的代碼。本質上,這個想法是,您要將類的屬性名稱連接到模式屬性名稱(schema.properties)。考慮到您可能有自定義序列化器設置(Camel Case),屬性名稱的外殼在模式中可能與類中定義的不同。 我還在SetSchemaDetails方法中包含父模式,以便您可以根據需要在父級別添加屬性。我們有偶爾使用的自定義必需屬性,因此我們需要在父級(包含類)架構級別而不是在屬性架構級別指定必需的屬性。

public class DataAnnotationSchemaFilter : ISchemaFilter 
{ 
    public void Apply(Schema schema, SchemaFilterContext schemaFilterContext) 
    { 
     var type = schemaFilterContext.SystemType; 

     var propertyMappings = type 
      .GetProperties() 
      .Join(
       schema.Properties ?? new Dictionary<string, Schema>(), 
       x => x.Name.ToLower(), 
       x => x.Key.ToLower(), 
       (x, y) => new KeyValuePair<PropertyInfo, KeyValuePair<string, Schema>>(x, y)) 
      .ToList(); 

     foreach (var propertyMapping in propertyMappings) 
     { 
      var propertyInfo = propertyMapping.Key; 
      var propertyNameToSchemaKvp = propertyMapping.Value; 

      foreach (var attribute in propertyInfo.GetCustomAttributes()) 
      { 
       SetSchemaDetails(schema, propertyNameToSchemaKvp, propertyInfo, attribute); 
      } 
     } 
    } 

    private static void SetSchemaDetails(Schema parentSchema, KeyValuePair<string, Schema> propertyNameToSchemaKvp, PropertyInfo propertyInfo, object propertyAttribute) 
    { 
     var schema = propertyNameToSchemaKvp.Value; 

     if (propertyAttribute is DataTypeAttribute) 
     { 
      var dataType = ((DataTypeAttribute)propertyAttribute).DataType; 
      if (dataType == DataType.Date) 
      { 
       schema.Format = "date"; 
       schema.Type = "date"; 
      } 
     } 

     if (propertyAttribute is ReadOnlyAttribute) 
     { 
      schema.ReadOnly = ((ReadOnlyAttribute)propertyAttribute).IsReadOnly; 
     } 
    } 
} 
+0

你能提供你的ISchemaFilter來自哪個命名空間嗎?我在'Swashbuckle.SwaggerGen.Generator.ISchemaFilter'中找到的那個沒有相同的函數原型。 – Sybeus

+0

Swashbuckle.Swagger.ISchemaFilter。我正在使用v5.4.0。 – fbhdev

+0

固定用於AspNetCore。 – fbhdev

相關問題