ASP.NET Core Web API多态请求体:如何让Swagger UI支持类型选择
ASP.NET Core Web API Swagger多态请求体类型选择问题
我正在开发ASP.NET Core Web API,需要允许客户端发送PUT请求时选择多种派生类型。已经通过基类、派生类配置了多态,并用自定义JsonConverter处理序列化,但Swagger UI只显示First类型的请求体选项,需要开启类型选择功能。
以下是我的模型、控制器及配置代码:
// Base class and derived classes public abstract class Base { public Type Type { get; set; } } public enum Type { First, Second } [JsonConverter(typeof(FirstConverter))] public class First : Base { public string Value { get; set; } } [JsonConverter(typeof(SecondConverter))] public class Second : Base { public string Data { get; set; } } // TestController [Route("api/[controller]")] [ApiController] public class TestController : ControllerBase { [HttpPut("/base")] public IActionResult First([FromBody] Base parameters) { return Ok(parameters); } } // Custom JsonConverter for polymorphism public class TestJsonConverter : JsonConverter<Base> { // Custom converter logic } // Swagger Configuration in Startup.cs or Program.cs builder.Services.AddSwaggerGen(options => { options.UseOneOfForPolymorphism(); options.UseAllOfForInheritance(); options.SchemaFilter<NotificationSettingsSchemaFilter>(); });
当前Swagger UI未提供First或Second类型的选择选项,请问我的Swagger配置缺失了什么?如何修改配置,让UI支持PUT请求体的类型选择?
问题原因
你的配置存在几个关键缺失:
- 未将自定义
TestJsonConverter注册到系统,Swagger无法识别多态类型映射逻辑 - 未显式声明
Base类的派生类型,Swagger仅能识别到标记了特性的First类 - 派生类上单独标注的
[JsonConverter]特性与全局多态转换器冲突
修复步骤
1. 移除派生类的JsonConverter特性
删除First和Second类上的[JsonConverter]特性,全局转换器会统一处理多态序列化:
// 修正后的First类 public class First : Base { public string Value { get; set; } } // 修正后的Second类 public class Second : Base { public string Data { get; set; } }
2. 注册全局多态转换器
在Program.cs(或Startup.cs)中,将TestJsonConverter添加到Json序列化配置:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new TestJsonConverter()); });
3. 配置Swagger显式识别派生类型
修改Swagger配置,添加自定义SchemaFilter声明Base的派生类,确保Swagger能渲染类型选择器:
builder.Services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo { Title = "Test API", Version = "v1" }); // 启用多态支持特性 options.UseOneOfForPolymorphism(); options.UseAllOfForInheritance(); // 添加自定义SchemaFilter options.SchemaFilter<BasePolymorphismSchemaFilter>(); }); // 自定义SchemaFilter,声明Base的派生类型 public class BasePolymorphismSchemaFilter : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext context) { if (context.Type == typeof(Base)) { // 注册所有派生类 schema.OneOf = new List<OpenApiSchema> { context.SchemaGenerator.GenerateSchema(typeof(First), context.SchemaRepository), context.SchemaGenerator.GenerateSchema(typeof(Second), context.SchemaRepository) }; schema.Description = "请选择请求体类型:First或Second"; // 添加discriminator配置,让Swagger识别类型字段 schema.Discriminator = new OpenApiDiscriminator { PropertyName = "Type", Mapping = new Dictionary<string, string> { { nameof(Type.First), "#/components/schemas/First" }, { nameof(Type.Second), "#/components/schemas/Second" } } }; } } }
4. 完善TestJsonConverter逻辑
确保自定义转换器能根据Type枚举值正确反序列化对应派生类,示例实现:
public class TestJsonConverter : JsonConverter<Base> { public override Base Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using var doc = JsonDocument.ParseValue(ref reader); if (!doc.RootElement.TryGetProperty(nameof(Type), out var typeElement)) throw new JsonException("缺少Type字段"); if (!Enum.TryParse<Type>(typeElement.GetString(), out var type)) throw new JsonException("无效的Type值"); return type switch { Type.First => doc.RootElement.Deserialize<First>(options), Type.Second => doc.RootElement.Deserialize<Second>(options), _ => throw new JsonException("不支持的请求体类型") }; } public override void Write(Utf8JsonWriter writer, Base value, JsonSerializerOptions options) { // 序列化时使用实际派生类类型 JsonSerializer.Serialize(writer, value, value.GetType(), options); } }
完成以上修改后,Swagger UI会在PUT请求的请求体区域显示类型选择下拉框,支持选择First或Second类型,同时请求体结构会自动切换为对应类型的字段。
内容的提问来源于stack exchange,提问作者DZziMD
相关产品推荐
相关产品推荐

