如何让Swagger.json标识列表/数组内的可空类型?
问题
希望Swagger.json能包含列表或数组内可空类型的信息,现有模型、Swagger配置及生成的JSON如下:
模型代码
public class AccountSettingsDto { public int Id { get; set; } public decimal? Value { get; set; } public List<decimal?> ListValue { get; set; } public decimal?[] ArrayValue { get; set; } }
当前Swagger配置
services.AddSwaggerGen(config => { config.MapType<decimal>(() => new OpenApiSchema { Type = "number", Format = "decimal" }); config.UseAllOfToExtendReferenceSchemas(); });
生成的Swagger JSON片段
"AccountSettingsDto": { "type": "object", "properties": { "id": { "type": "integer", "format": "int32" }, "value": { "type": "number", "format": "decimal", "nullable": true }, "listValue": { "type": "array", "items": { "type": "number", "format": "decimal" }, "nullable": true }, "arrayValue": { "type": "array", "items": { "type": "number", "format": "decimal" }, "nullable": true } }, "additionalProperties": false }
可见Value属性的可空标识正确,但列表/数组内的元素未正确标记可空。曾尝试添加config.MapType<decimal?>(() => new OpenApiSchema { Type = "number", Format = "decimal?" });但无效。
解决方案
要让数组/列表的元素显示可空标识,需通过SchemaFilter遍历并修改数组的items schema——MapType仅针对顶层属性类型,无法处理嵌套在数组内的可空类型。
步骤1:实现自定义SchemaFilter
创建NullableArrayItemSchemaFilter类,实现ISchemaFilter接口,检查数组元素是否为可空值类型,为items添加nullable: true标识:
using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using System.Reflection; public class NullableArrayItemSchemaFilter : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext context) { if (schema.Type == "array" && schema.Items != null) { var propertyInfo = context.MemberInfo as PropertyInfo; if (propertyInfo == null) return; // 提取数组/列表的元素类型 Type elementType = null; if (propertyInfo.PropertyType.IsArray) { elementType = propertyInfo.PropertyType.GetElementType(); } else if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(List<>)) { elementType = propertyInfo.PropertyType.GetGenericArguments()[0]; } // 标记可空值类型的元素为nullable if (elementType != null && elementType.IsGenericType && elementType.GetGenericTypeDefinition() == typeof(Nullable<>)) { schema.Items.Nullable = true; // 确保decimal类型的格式正确 if (elementType.GetGenericArguments()[0] == typeof(decimal)) { schema.Items.Type = "number"; schema.Items.Format = "decimal"; } } } } }
步骤2:注册SchemaFilter到Swagger配置
修改AddSwaggerGen配置,添加自定义过滤器:
services.AddSwaggerGen(config => { config.MapType<decimal>(() => new OpenApiSchema { Type = "number", Format = "decimal" }); config.UseAllOfToExtendReferenceSchemas(); // 注册自定义过滤器 config.SchemaFilter<NullableArrayItemSchemaFilter>(); });
最终效果
修改后生成的Swagger JSON中,数组的items会包含nullable: true:
"listValue": { "type": "array", "items": { "type": "number", "format": "decimal", "nullable": true }, "nullable": true }, "arrayValue": { "type": "array", "items": { "type": "number", "format": "decimal", "nullable": true }, "nullable": true }
补充说明
之前尝试的MapType<decimal?>无效,是因为Swashbuckle处理数组元素时,不会直接复用MapType配置的可空类型映射,而是解析元素原始类型生成schema,因此必须通过SchemaFilter手动处理嵌套的可空元素。
内容的提问来源于stack exchange,提问作者Guillaume
相关产品推荐
相关产品推荐

