web-dev-qa-db-ja.com

モデルのプロパティを無視するようにSwashbuckleを構成する方法

Swashbuckleを使用して、webapi2プロジェクトのswagger documentation\UIを生成しています。モデルはいくつかのレガシーインターフェイスと共有されているため、モデルで無視したいプロパティがいくつかあります。レガシインターフェイスもJSONにシリアル化する必要があるため、JsonIgnore属性を使用できません。そのため、Swashbuckle構成でプロパティをグローバルに無視したくありません。

私はここで文書化されたこれを行う方法を見つけました:

https://github.com/domaindrivendev/Swashbuckle/issues/7

しかし、これは現在のスワッシュバックルのリリースでは時代遅れのようです。

Swashbuckleの古いバージョンに推奨される方法は、次のようにIModelFilter実装を使用しています。

public class OmitIgnoredProperties : IModelFilter
{
    public void Apply(DataType model, DataTypeRegistry dataTypeRegistry, Type type)
    {
        var ignoredProperties = … // use reflection to find any properties on 
                                  // type decorated with the ignore attributes

        foreach (var prop in ignoredProperties) 
            model.Properties.Remove(prop.Name);

    }
}

SwaggerSpecConfig.Customize(c => c.ModelFilter<OmitIgnoredProperties>());

しかし、現在のバージョンでIModelFilterを使用するようにSwashbuckleを構成する方法がわかりませんか? Swashbuckle 5.5.3を使用しています。

29
mutex

JsonIgnoreを使用せずにこれを実行する必要がある場合(プロパティのシリアル化/逆シリアル化が必要な場合があります)、カスタム属性を作成します。

[AttributeUsage(AttributeTargets.Property)]
public class SwaggerExcludeAttribute : Attribute
{
}

次に、 Johng's に似たスキーマフィルター

public class SwaggerExcludeFilter : ISchemaFilter
{
    #region ISchemaFilter Members

    public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
    {
        if (schema?.Properties == null || type == null)
            return;

        var excludedProperties = type.GetProperties()
                                     .Where(t => 
                                            t.GetCustomAttribute<SwaggerExcludeAttribute>() 
                                            != null);

        foreach (var excludedProperty in excludedProperties)
        {
            if (schema.properties.ContainsKey(excludedProperty.Name))
                schema.properties.Remove(excludedProperty.Name);
        }
    }

    #endregion
}

フィルターを登録することを忘れないでください

c.SchemaFilter<SwaggerExcludeFilter>();
27
Richard

フィールド/プロパティにinternalまたはprotectedまたはprivateのマークを付けると、swaggerドキュメントのスワッシュバックルによって自動的に無視されます。

18
Jay Shah

AspNetCoreソリューションは次のようになります。

public class SwaggerExcludeSchemaFilter : ISchemaFilter
{
    public void Apply(Schema schema, SchemaFilterContext context)
    {
        if (schema?.Properties == null)
        {
            return;
        }

        var excludedProperties = context.SystemType.GetProperties().Where(t => t.GetCustomAttribute<SwaggerExcludeAttribute>() != null);
        foreach (PropertyInfo excludedProperty in excludedProperties)
        {
            if (schema.Properties.ContainsKey(excludedProperty.Name))
            {
                schema.Properties.Remove(excludedProperty.Name);
            }
        }
    }
}
11
Stef Heyenrath

さて、少し突っ込んで、ISchemaFilterを使用してこれを行う方法を見つけました。

public class ApplyCustomSchemaFilters : ISchemaFilter
{
    public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
    {
        var excludeProperties = new[] {"myProp1", "myProp2", "myProp3"};

        foreach(var prop in excludeProperties)
            if (schema.properties.ContainsKey(prop))
                schema.properties.Remove(prop);
    }
}

次に、httpConfiguration.EnableSwaggerを呼び出すときに、SwaggerDocsConfigを設定して、このSchemaFilterを次のように使用します。

c.SchemaFilter<ApplyCustomSchemaFilters>();

これが誰かを助けることを願っています。それでも、どういうわけかIModelFilterを使用できるかどうかについては、まだ興味があります。

9
mutex

以下のコードは@Richardの回答に非常に基づいていますが、3つのまったく新しい便利な機能が追加されているため、新しい回答として含めています。

  • Swashbuckleの最新バージョン(v5)の.NET Coreで実行
  • プロパティだけでなくフィールドにSwaggerIgnore属性を適用できます
  • JsonProperty属性を使用してプロパティ名とフィールド名がオーバーライドされた可能性があるという事実を処理します
  • 編集:元々のTitleCasedフィールドまたはプロパティのcamelCasingを正しく処理するようになりました(@mattrumaの答えが求められます)

改訂されたコードは次のとおりです。

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class SwaggerIgnoreAttribute : Attribute
{
}
internal static class StringExtensions
{
    internal static string ToCamelCase(this string value)
    {
        if (string.IsNullOrEmpty(value)) return value;
        return char.ToLowerInvariant(value[0]) + value.Substring(1);
    }
}
public class SwaggerIgnoreFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext schemaFilterContext)
    {
        if (schema.Properties.Count == 0)
            return;

        const BindingFlags bindingFlags = BindingFlags.Public |
                                          BindingFlags.NonPublic |
                                          BindingFlags.Instance;
        var memberList = schemaFilterContext.SystemType
                            .GetFields(bindingFlags).Cast<MemberInfo>()
                            .Concat(schemaFilterContext.SystemType
                            .GetProperties(bindingFlags));

        var excludedList = memberList.Where(m =>
                                            m.GetCustomAttribute<SwaggerIgnoreAttribute>()
                                            != null)
                                     .Select(m =>
                                         (m.GetCustomAttribute<JsonPropertyAttribute>()
                                          ?.PropertyName
                                          ?? m.Name.ToCamelCase()));

        foreach (var excludedName in excludedList)
        {
            if (schema.Properties.ContainsKey(excludedName))
                schema.Properties.Remove(excludedName);
        }
    }
}

およびStartup.cs

services.AddSwaggerGen(c =>
{
    ...
    c.SchemaFilter<SwaggerIgnoreFilter>();
    ...
});
8
Mike Beaton

Stef Heyenrathの回答に基づく

Swaggerのドキュメントから除外するプロパティをマークする属性。

[AttributeUsage(AttributeTargets.Property)]
public class SwaggerExcludeAttribute : Attribute
{
}

Swaggerドキュメントからプロパティを除外するフィルター。

public class SwaggerExcludeSchemaFilter : ISchemaFilter
{
    public void Apply(Schema schema, SchemaFilterContext context)
    {
        if (schema?.Properties == null)
        {
            return;
        }

        var excludedProperties = 
            context.SystemType.GetProperties().Where(
                t => t.GetCustomAttribute<SwaggerExcludeAttribute>() != null);

        foreach (var excludedProperty in excludedProperties)
        {
            var propertyToRemove =
                schema.Properties.Keys.SingleOrDefault(
                    x => x.ToLower() == excludedProperty.Name.ToLower());

            if (propertyToRemove != null)
            {
                schema.Properties.Remove(propertyToRemove);
            }
        }
    }
}

schema.Properties.KeyscamelCaseですが、プロパティ自体はPascalCaseです。両方を小文字に変換し、何を除外すべきかを比較する方法を調整しました。

4
mattruma

ミューテックスの答えに基づく 。)

NullReferenceExceptionに問題がないように別の行を追加しました。

public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
{
  var excludeProperties = new[] { "myProp1", "myProp2, myProp3"};

   foreach (var prop in excludeProperties)
     if(schema.properties != null) // This line
       if (schema.properties.ContainsKey(prop))
        schema.properties.Remove(prop);        
}

すべてのスキーマを削除する場合

public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
{
  schema.properties = null;       
} 

Newtonsoft.Json.JsonIgnoreAttributeで使用したものは次のとおりです。

internal class ApplySchemaVendorExtensions : Swashbuckle.Swagger.ISchemaFilter
{
    public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
    {
        foreach (var prop in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
                                 .Where(p => p.GetCustomAttributes(typeof(Newtonsoft.Json.JsonIgnoreAttribute), true)?.Any() == true))
            if (schema?.properties?.ContainsKey(prop.Name) == true)
                schema?.properties?.Remove(prop.Name);
    }
}
3
johng

。Net Coreを使用しており、app.UseSwaggerUi3WithApiExplorer()のビルドを使用している私のような人々のために

つかいます [JsonIgnore]タグを使用してNewtonsoft.Json;

public class Project
{
    [Required]
    public string ProjectName { get; set; }

    [JsonIgnore]
    public string SomeValueYouWantToIgnore { get; set; }
}

ドキュメントから除外されます。

3
Jorben Saaltink