ASP.NET Core Web API如何反序列化Swagger的oneOf类型请求体?
解决ASP.NET Core 6最小API多态JSON反序列化问题
1. 配置System.Text.Json的多态支持
默认的System.Text.Json不自动处理多态类型转换,需要通过配置类型映射和鉴别字段,让反序列化器识别子类。
示例代码
先定义你的形状类:
public abstract class Shape { // 自定义类型鉴别字段,用于标识具体子类 public string Type { get; set; } } public class Circle : Shape { public double Radius { get; set; } } public class Square : Shape { public double SideLength { get; set; } }
在Program.cs中配置Json序列化选项,添加多态类型信息:
builder.Services.Configure<JsonOptions>(options => { options.SerializerOptions.TypeInfoResolverChain.Insert(0, CreateShapePolymorphicTypeInfo()); }); // 构建多态类型映射规则 private static JsonTypeInfo CreateShapePolymorphicTypeInfo() { var context = new JsonSerializerContext(new JsonSerializerOptions()); var shapeTypeInfo = context.GetTypeInfo(typeof(Shape)) as JsonDerivedTypeInfo; // 绑定子类与鉴别字段值 shapeTypeInfo.DerivedTypes.Add(new JsonDerivedType(typeof(Circle), "Circle")); shapeTypeInfo.DerivedTypes.Add(new JsonDerivedType(typeof(Square), "Square")); return shapeTypeInfo; }
2. 同步Swagger配置以匹配鉴别规则
为了让Swagger文档正确提示客户端传入类型鉴别字段,需要调整Swashbuckle配置:
builder.Services.AddSwaggerGen(c => { c.UseOneOfForPolymorphism(); // 指定基类对应的子类集合 c.SelectSubTypesUsing(baseType => { if (baseType == typeof(Shape)) { return new[] { typeof(Circle), typeof(Square) }; } return Enumerable.Empty<Type>(); }); // 添加鉴别字段到Swagger Schema c.SchemaFilter<PolymorphismSchemaFilter>(); }); // 自定义SchemaFilter,完善Swagger文档中的类型鉴别字段定义 public class PolymorphismSchemaFilter : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext context) { if (context.Type == typeof(Shape)) { schema.Properties["Type"] = new OpenApiSchema { Type = "string", Enum = new List<IOpenApiAny> { new OpenApiString("Circle"), new OpenApiString("Square") } }; schema.Required.Add("Type"); } } }
3. 适配复杂对象的部分字段场景
如果是复杂对象中的某个字段为多态类型(比如public class User { public Shape FavoriteShape { get; set; } }),上述全局配置依然生效。只要JSON中对应字段包含正确的类型鉴别值,反序列化器就能自动将其转换为对应的子类。
关键注意事项
- 确保子类有符合要求的构造函数(无参、单参数或标记
JsonConstructorAttribute的参数化构造函数),避免出现你遇到的构造函数异常 - 类型鉴别字段的名称和值,要在Json配置与Swagger配置中完全一致
- 若使用默认的
$type字段,客户端需传入包含类型全名的字符串(如"$type": "YourNamespace.Circle, YourAssembly"),自定义字段对客户端更友好
配置完成后,客户端传入如下JSON即可正确反序列化为Circle子类:
{ "Type": "Circle", "Radius": 5.0 }
内容的提问来源于stack exchange,提问作者Overlord Zurg
相关产品推荐
相关产品推荐

