Как настроить Swashbuckle для игнорирования свойства на модели
Я использую Swashbuckle для генерации документации Swagger\UI для проекта webapi2. Наши модели используются совместно с некоторыми устаревшими интерфейсами, поэтому есть несколько свойств, которые я хочу игнорировать в моделях. Я не могу использовать атрибут JsonIgnore, потому что устаревшие интерфейсы также должны сериализоваться в JSON, поэтому я не хочу игнорировать свойства глобально, только в конфигурации Swashbuckle.
Я нашел способ сделать это, документированный здесь:
https://github.com/domaindrivendev/Swashbuckle/issues/73
Но это, кажется, устарело с текущей версией Swashbuckle.
Метод, рекомендуемый для старой версии 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>());
Но я не уверен, как настроить Swashbuckle для использования IModelFilter в текущей версии? Я использую Swashbuckle 5.5.3.
Ответы
Ответ 1
Если вам нужно это сделать, но без использования 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>();
Ответ 2
Если вы помечаете поле/свойство как internal
protected
или private
, оно будет автоматически проигнорировано с помощью swashbuckle в документации swagger.
Ответ 3
Решение 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);
}
}
}
}
Ответ 4
Ну, с небольшим ворсом я нашел способ сделать это, используя 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.
Ответ 5
Приведенный ниже код в значительной степени основан на ответе @Richard, но я включил его в качестве нового ответа, поскольку в нем есть три совершенно новых полезных функции, которые я добавил:
- Работает на .NET Core в последней версии Swashbuckle (v5)
- Позволяет
SwaggerIgnore
атрибут SwaggerIgnore
к полям, а не только к свойствам - Обрабатывает тот факт, что имена свойств и полей могли быть переопределены с
JsonProperty
атрибута JsonProperty
- РЕДАКТИРОВАТЬ: теперь корректно обрабатывает camelCasing исходных полей или свойств TitleCased (подсказка ответа @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>();
...
});
Ответ 6
Основано на ответе 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.Keys
- это camelCase
, а сами свойства - PascalCase
. Настроил метод преобразования обоих в нижний регистр и сравнения, чтобы увидеть, что должно быть исключено.
Ответ 7
(На основе ответа мьютекса.)
Я добавил еще одну строку, чтобы не иметь проблем с 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;
}
Ответ 8
Вот что я использовал с 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);
}
}
Ответ 9
Для таких людей, как я, которые используют .Net Core и используют встроенное приложение. app.UseSwaggerUi3WithApiExplorer()
Используйте тег [JsonIgnore]
используя Newtonsoft.Json;
public class Project
{
[Required]
public string ProjectName { get; set; }
[JsonIgnore]
public string SomeValueYouWantToIgnore { get; set; }
}
Это будет исключено из вашей документации.
Ответ 10
Как добавить свойства в схему в классе SwaggerDocument. Как я могу сделать это, я хочу добавить новую модель "Ошибка": тип: объект Свойства: Код ошибки: Описание ошибки:
Ответ 11
Я использую Nswag вместо Swashbuckle. Кто-нибудь знает, есть ли какое-либо соответствие для интерфейса "ISchemaFilter" в Nswag?
Ответ 12
У меня есть рабочий пример с DotNetCore 3 и Swashbuckle 5. Мне потребовалось несколько часов, чтобы установить его, поэтому я решил вернуться к этой теме, которая помогла мне, но не решила мою проблему.
Создайте фиктивный пользовательский атрибут:
[AttributeUsage(AttributeTargets.Property)]
public class SwaggerExcludeAttribute : Attribute { }
Создайте SchemaFilter, который будет использоваться Swagger для генерации схемы модели API
public class SwaggerExcludeFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (!(context.ApiModel is ApiObject))
{
return;
}
var model = context.ApiModel as ApiObject;
if (schema?.Properties == null || model?.ApiProperties == null)
{
return;
}
var excludedProperties = model.Type
.GetProperties()
.Where(
t => t.GetCustomAttribute<SwaggerExcludeAttribute>() != null
);
var excludedSchemaProperties = model.ApiProperties
.Where(
ap => excludedProperties.Any(
pi => pi.Name == ap.MemberInfo.Name
)
);
foreach (var propertyToExclude in excludedSchemaProperties)
{
schema.Properties.Remove(propertyToExclude.ApiName);
}
}
}
Затем в файле Startup.cs
добавьте это в конфигурацию сваггера
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
c.SchemaFilter<SwaggerExcludeFilter>();
});
Теперь вы можете использовать настраиваемый атрибут для свойства, которое вы хотите исключить из схемы режима API, например
public class MyApiModel
{
[SwaggerExclude]
public Guid Token { get; set; }
public int Id { get; set; }
public string Name { get; set; }
}