Swashbuckle.AspNetCore.SwaggerGen v5中如何获取JsonContract?
在Swashbuckle.AspNetCore.SwaggerGen v5版本中获取JsonContract的方案
背景
在Swashbuckle.AspNetCore.SwaggerGen v4.0.1.0版本中,实现了如下ISchemaFilter用于将非可空值类型属性标记为必填:
public class RequireNonNullableValueTypePropertiesSchemaFilter : ISchemaFilter { public void Apply(Schema schema, SchemaFilterContext context) { if (schema.Type == "object" && context.JsonContract is JsonObjectContract jsonObjectContract) { var valueTypeProperties = jsonObjectContract.Properties .Where(property => property.PropertyType.IsValueType) .Where(property => !property.PropertyType.IsGenericType || property.PropertyType.GetGenericTypeDefinition() != typeof(Nullable<>)) .Select(property => property.PropertyName) .ToList(); if (valueTypeProperties.Count > 0) { if (schema.Required == null) { schema.Required = new List<string>(); } foreach (var valueTypeProperty in valueTypeProperties.Except(schema.Required)) { schema.Required.Add(valueTypeProperty); } } } } }
升级至v5版本后,SchemaFilterContext移除了JsonContract属性,导致原代码中的核心判断逻辑失效。经过一周调研和尝试(因项目架构限制无法在DLL中调试断点),仍未找到替代方案。
项目架构信息:
- 解决方案包含多个服务契约类库(ServiceContract1、ServiceContract2等)
- 所有契约类库依赖同一个ServiceExtensions类库
- 契约类库发布为NuGet包,由外部控制台应用加载
- 外部控制台应用通过加载这些NuGet包生成Swagger文档
解决方案
在v5版本中,SchemaFilterContext提供了SerializerOptions属性,可通过该属性获取配置的契约解析器,进而获取目标类型的JsonContract。重构后的代码如下:
using Newtonsoft.Json.Serialization; public class RequireNonNullableValueTypePropertiesSchemaFilter : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext context) { // v5版本中Schema已替换为OpenApiSchema if (schema.Type == "object" && context.Type != null) { // 从SerializerOptions中获取JsonSerializerSettings及契约解析器 var jsonSettings = context.SerializerOptions as JsonSerializerSettings; if (jsonSettings?.ContractResolver == null) return; var jsonContract = jsonSettings.ContractResolver.ResolveContract(context.Type); if (jsonContract is not JsonObjectContract jsonObjectContract) return; var valueTypeProperties = jsonObjectContract.Properties .Where(p => p.PropertyType.IsValueType) .Where(p => !p.PropertyType.IsGenericType || p.PropertyType.GetGenericTypeDefinition() != typeof(Nullable<>)) .Select(p => p.PropertyName) .ToList(); if (valueTypeProperties.Count == 0) return; // v5版本中Required属性类型为HashSet<string> schema.Required ??= new HashSet<string>(); foreach (var propertyName in valueTypeProperties.Except(schema.Required)) { schema.Required.Add(propertyName); } } } }
关键调整说明
- 类型替换:v5版本中
Schema类已被OpenApiSchema替代,需同步修改方法参数类型。 - Required属性类型变更:原
List<string>改为HashSet<string>,使用??=简化初始化逻辑。 - 获取JsonContract的新方式:通过
context.SerializerOptions转换为JsonSerializerSettings,再利用ContractResolver.ResolveContract方法获取目标类型的契约。 - 空值判断优化:使用C# 8.0+的
is not和空合并运算符简化代码逻辑。
内容的提问来源于stack exchange,提问作者forever_learner
相关产品推荐
相关产品推荐

