mut*_*tex 32 c# asp.net-web-api swagger swashbuckle
我正在使用Swashbuckle为webapi2项目生成swagger文档\ UI.我们的模型与一些传统接口共享,因此我想在模型上忽略一些属性.我不能使用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>());
Run Code Online (Sandbox Code Playgroud)
但我不确定如何配置Swashbuckle在当前版本中使用IModelFilter?我正在使用Swashbuckle 5.5.3.
Ric*_*ard 35
如果你需要做到这一点,但没有使用JsonIgnore(也许你还需要序列化/反序列化属性),那么只需要创建一个自定义属性.
[AttributeUsage(AttributeTargets.Property)]
public class SwaggerExcludeAttribute : Attribute
{
}
Run Code Online (Sandbox Code Playgroud)
然后是类似于Johng的模式过滤器
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
}
Run Code Online (Sandbox Code Playgroud)
不要忘记注册过滤器
c.SchemaFilter<SwaggerExcludeFilter>();
Run Code Online (Sandbox Code Playgroud)
Veg*_*ter 30
.NET Core 3.1和.NET Standard 2.1 的解决方案:
JsonIgnore
从System.Text.Json.Serialization
命名空间使用。
(JsonIgnore
从Newtonsoft.Json
不起作用)
public class Test
{
[System.Text.Json.Serialization.JsonIgnore]
public int HiddenProperty { get; set; }
public int VisibleProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
Jay*_*hah 19
如果标记字段/属性的internal
或protected
或者private
,它会自动通过swashbuckle招摇文档中被忽略.
Ste*_*ath 12
该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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
mut*_*tex 11
好吧,有点戳,我找到了一种方法来使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后在调用时httpConfiguration.EnableSwagger
我将SwaggerDocsConfig
如下设置使用此SchemaFilter:
c.SchemaFilter<ApplyCustomSchemaFilters>();
Run Code Online (Sandbox Code Playgroud)
希望这有助于某人.我仍然对是否有可能以某种方式使用IModelFilter感到好奇.
小智 11
对于像我这样使用.Net Core 并使用内置的人app.UseSwaggerUi3WithApiExplorer()
使用Newtonsoft.Json[JsonIgnore]
标记;
public class Project
{
[Required]
public string ProjectName { get; set; }
[JsonIgnore]
public string SomeValueYouWantToIgnore { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
它将从您的文档中排除。
Han*_*abi 10
您可以使用该Swashbuckle.AspNetCore.Annotations
包,它允许您标记某些属性仅显示在输入参数中,某些属性仅显示在输出中。
例如,如果您想隐藏AlertId
帖子的输入参数中的 ,则只需通过以下操作即可[SwaggerSchema]
:
public class Alert
{
[SwaggerSchema(ReadOnly = true)]
public string AlertId { get; set; }
public string Type { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在文档中查看更多相关信息
下面的代码很大程度上基于@Richard的答案,但我将其作为新答案包括在内,因为它具有三个全新的有用功能,我已经添加了它们:
SwaggerIgnore
属性应用于字段,而不仅仅是属性JsonProperty
属性覆盖的事实因此,修改后的代码为:
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class SwaggerIgnoreAttribute : Attribute
{
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
并在Startup.cs
:
services.AddSwaggerGen(c =>
{
...
c.SchemaFilter<SwaggerIgnoreFilter>();
...
});
Run Code Online (Sandbox Code Playgroud)
小智 7
我在这里有一个 DotNetCore 3 和 Swashbuckle 5 的工作示例。我花了几个小时才把它安装到位,所以我想回到这个对我有帮助但没有解决我的问题的线程。
创建一个虚拟的自定义属性:
[AttributeUsage(AttributeTargets.Property)]
public class SwaggerExcludeAttribute : Attribute { }
Run Code Online (Sandbox Code Playgroud)
创建一个 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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在Startup.cs
文件中将其添加到 swagger 配置中
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
c.SchemaFilter<SwaggerExcludeFilter>();
});
Run Code Online (Sandbox Code Playgroud)
您现在可以在要从 API 模式 Shema 中排除的属性上使用自定义属性,如下所示
public class MyApiModel
{
[SwaggerExclude]
public Guid Token { get; set; }
public int Id { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
标记要从Swagger文档中排除的属性的属性。
[AttributeUsage(AttributeTargets.Property)]
public class SwaggerExcludeAttribute : Attribute
{
}
Run Code Online (Sandbox Code Playgroud)
从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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
的schema.Properties.Keys
是camelCase
,虽然性质本身PascalCase
。调整了将小写转换为小写并进行比较以查看应排除的方法。
小智 5
Swashbuckle 现在支持 Newtonsoft。 https://github.com/domaindrivendev/Swashbuckle.AspNetCore#systemtextjson-stj-vs-newtonsoft
dotnet add package --version 5.3.1 Swashbuckle.AspNetCore.Newtonsoft
`services.AddSwaggerGenNewtonsoftSupport(); // explicit opt-in - needs tobe placed after AddSwaggerGen();`
Run Code Online (Sandbox Code Playgroud)
这是一个较老的问题,但 Swashbuckle 中已经提供了一种省力的中间解决方案。
从文档中隐藏遗留属性并不能阻止这些属性的使用——它只是延迟了发现。毕竟,它们仍然是模型的一部分。事实上,没有记录就意味着消费者无法知道他们不应该使用它们!
您应该简单地考虑对它们进行标记,而不是让它们没有记录[Obsolete]
。
然后,Swashbuckle 会在 swagger.json 中将它们标记为已弃用。在 UI 中,这会将它们隐藏在“示例值”部分中,而在“架构”部分中,它们将显示为灰色,并在名称上带有删除线。
如果您仍然希望它们在文档中完全隐藏,则可以在SwaggerGeneratorOptions.IgnoreObsoleteProperties = true
.
在最初提出这个问题时,这不是一个可能的解决方案。已弃用标志是 OpenAPI v3 的一项功能,直到 2017 年才发布。