2.13 自定义架构id
如果在文档生成器遇到复杂的传入参数或响应类型,生成器会自动生成相应Json Schema
,并将其添加到全局Components/Schemas
字典中。
还是以天气类WeatherForecast
,默认情况下,Api Json
对应请求链接http://localhost:5000/v1/swaggerapi.json
内容大致如下:
{ "paths": { "/WeatherForecast": { "get": { "tags": [ "GET" ], "summary": "获取天气预报信息", "responses": { "201": { "description": "请求成功并且服务器创建了新的资源", "content": { "text/plain": { "schema": { "type": "array", "items": { // #/components/schemas/{schemasid} "$ref": "#/components/schemas/WeatherForecast" } } } } } } } } }, "components": { "schemas": { "WeatherForecast": { "type": "object", "properties": { "date": { "type": "string", "description": "日期", "format": "date-time" } }, "additionalProperties": false, "description": "天气预报实体" } } } }
修改服务中ConfigureServices
的配置,自定义标识的生成规则CustomSchemaIds
,
public void ConfigureServices(IServiceCollection services) { services.AddSwaggerGen( options => { #region 自定义架构Id // 输出对应类型全名称 options.CustomSchemaIds(schema => schema.FullName); #endregion } ); }
运行后,对应输出的Json
结构如下:
{ "paths": { "/WeatherForecast": { "get": { "tags": [ "GET" ], "summary": "获取天气预报信息", "responses": { "201": { "description": "请求成功并且服务器创建了新的资源", "content": { "text/plain": { "schema": { "type": "array", "items": { // #/components/schemas/{schemasid} "$ref": "#/components/schemas/swaggertestbase.WeatherForecast" } } } } } } } } }, "components": { "schemas": { // {schemasid} "swaggertestbase.WeatherForecast": { "type": "object", "properties": { "date": { "type": "string", "description": "日期", "format": "date-time" } }, "additionalProperties": false, "description": "天气预报实体" } } } }
2.14 覆盖特定类型架构[不常用]
需要对特定类型进行指定序列化处理时,可以通过自定义架构序列化类型处理。
数据实体类:
/// <summary> /// 天气预报实体 /// </summary> public class WeatherForecast { /// <summary> /// 日期 /// </summary> public DateTime Date { get; set; } /// <summary> /// 温度-摄氏度 /// </summary> public int TemperatureC { get; set; } /// <summary> /// 温度-华摄氏度 /// </summary> public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); /// <summary> /// 描述 /// </summary> public string Summary { get; set; } }
请求http://localhost:5000/v1/swaggerapi.json
,原始Json
架构如下:
"components": { "schemas": { "WeatherForecast": { "type": "object", "properties": { "date": { "type": "string", "description": "日期", "format": "date-time" }, "temperatureC": { "type": "integer", "description": "温度-摄氏度", "format": "int32" }, "temperatureF": { "type": "integer", "description": "温度-华摄氏度", "format": "int32", "readOnly": true }, "summary": { "type": "string", "description": "描述", "nullable": true } }, "additionalProperties": false, "description": "天气预报实体" } } }
修改ConfigureServices
中的AddSwaggerGen
,设定类型序列化的架构为字符串。
services.AddSwaggerGen( options => { #region 覆盖特定类型架构 // 指定对应的实体类型,类型架构配置 options.MapType<WeatherForecast>(() => new Microsoft.OpenApi.Models.OpenApiSchema { Type = "string" }); #endregion } );
设置以后,对应的类型在架构中,无生成,目前无考虑深究原因,运行效果如下:
2.15 使用过滤器扩展生成器
1)操作过滤器
Swashbuckle
会检索每一个Asp.Net Core
中的每一个ApiDescription
,从中提取到对应的OpenApiOperation
,对应OpenApiOperation
类型和ApiDescription
能够通过操作过滤器列表实现传递。以包含权限认证
特性,响应中401
响应状态的操作过滤器为例。
创建类AuthResponsesOperationFilter
实现IOperationFilter
,
public class AuthResponsesOperationFilter : IOperationFilter { public void Apply(OpenApiOperation operation, OperationFilterContext context) { var customAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true) .Union(context.MethodInfo.GetCustomAttributes(true)) .OfType<AuthorizeAttribute>(); if (customAttributes.Any()) { operation.Responses.Add("401", new OpenApiResponse { Description = "UnAuthorized" }); } } }
给控制器中WeatherForecastController
对应Post
函数添加特性Authorize
/// <summary> /// 天气预报服务 /// </summary> [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { ........ /// <summary> /// 获取Post数据 /// </summary> /// <returns>处理结果</returns> [HttpPost] [Authorize] public string Post() { return "处理结果"; } ........ }
添加到动作过滤器列表中,
services.AddSwaggerGen( options => { #region 添加权限认证响应操作过滤器 options.OperationFilter<AuthResponsesOperationFilter>(); #endregion } );
运行效果如下:
需要注意的是,过滤器管道是DI
感知的。 可以使用构造函数参数创建过滤器,只要参数类型已在DI
框架中注册,则它们将在过滤器实例化时自动注入。
2)架构过滤器
Swashbuckle
为控制器操作公开的每个参数、响应和属性类型生成 Swagger 样式的 JSONSchema
。 生成后,它通过配置的架构过滤器列表传递架构和类型。
创建枚举类型,
/// <summary> /// 自定义枚举 /// </summary> public enum MyEnum { A, B, C }
创建SchemaFilterController
控制器,
[Route("api/[controller]")] [ApiController] public class SchemaFilterController : ControllerBase { /// <summary> /// 获取SchemaFilter过滤器数据 /// </summary> /// <param name="my">枚举参数</param> [HttpGet] public void Get(MyEnum my) { } }
自定义类AutoRestSchemaFilter
,实现ISchemaFilter
,
/// <summary> /// 自动设置架构过滤器 /// </summary> public class AutoRestSchemaFilter : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext context) { var type = context.Type; if (type.IsEnum) { schema.Extensions.Add("x-ms-enum", new OpenApiObject() { ["name"] = new OpenApiString(type.Name), ["modelAsString"] = new OpenApiBoolean(true) }); } } }
添加到架构过滤器中,
.... services.AddSwaggerGen( options => { #region 添加自定义架构过滤器 options.SchemaFilter<AutoRestSchemaFilter>(); #endregion }); ....
访问http://localhost:5000/v1/swaggerapi.json
,可以看到对应结构如下如下,x-ms-enum
在对应类型的架构尾部。
{ "components": { "schemas": { "MyEnum": { "enum": [ 0, 1, 2 ], "type": "integer", "description": "自定义枚举", "format": "int32", "x-ms-enum": { "name": "MyEnum", "modelAsString": true } } } } }
通过上述例子,可以看出,对于枚举等特殊类型,实际可以通过自定义Json schema
的方式实现对应字段值的备注含义。
3)文档过滤器
Document Filters
在遵守OpenApi
的规范前提下,可以通过文档过滤器对文档进行任意有效的Swagger Json
。例如为当前文档添加额外的Tags
,自定义过滤器TagDescriptionsDocumentFilter
,实现IDocumentFilter
,
/// <summary> /// Tag描述文档过滤器 /// </summary> public class TagDescriptionsDocumentFilter : IDocumentFilter { public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { swaggerDoc.Tags = new List<OpenApiTag> { new OpenApiTag{ Name ="Pages", Description = "分页类" }, new OpenApiTag{ Name ="Tests", Description = "测试类" } }; } }
添加到现有的文档过滤器中,
public void ConfigureServices(IServiceCollection services) { services.AddSwaggerGen( options => { //忽略部分内容 #region 添加自定义文档过滤器 options.DocumentFilter<TagDescriptionsDocumentFilter>(); #endregion //忽略部分内容 } ); }
请求http://localhost:5000/v1/swaggerapi.json
,在返回结果中能够看到如下部分结构:
{ //忽略无关项 "tags": [ { "name": "Pages", "description": "分页类" }, { "name": "Tests", "description": "测试类" } ] }
后续文章将讲解为Swagger
添加安全验证。