如何将请求体反序列化为子类?ASP.NET后端OpenAPI生成问题
解决ASP.NET后端反序列化OpenAPI多态类的问题
我之前碰到过几乎一模一样的问题,核心是两个关键点:完善OpenAPI定义中的鉴别器映射,以及确保代码生成工具正确启用多态反序列化支持。下面是具体的解决步骤:
1. 完善OpenAPI定义中的鉴别器配置
你的OpenAPI定义已经使用了discriminator,但缺少子类映射——ASP.NET需要明确知道className字段的值对应哪个具体子类。修改Animal schema的discriminator部分,添加mapping节点:
Animal: type: object discriminator: propertyName: className # 添加这部分映射,明确className值对应的子类schema mapping: Cat: '#/components/schemas/Cat' Dog: '#/components/schemas/Dog' required: - "id" - "name" - "className" properties: id: type: string description: The unique ID of this object format: uuid example: 3fa85f64-5717-4562-b3fc-2c963f66afa6 name: type: string description: Gives a name to the animal example: Bob className: type: string description: Determines which child class this object is example: Cat
这个映射告诉代码生成工具:当请求中className的值为Cat时,反序列化为Cat类;值为Dog时反序列化为Dog类。
2. 调整代码生成工具的配置
根据你使用的代码生成工具(NSwag或OpenAPI Generator),启用多态支持:
如果使用NSwag(ASP.NET常用工具)
在你的nswag.json配置文件中,确保添加以下参数,开启鉴别器的自动处理:
{ "codeGenerators": { "aspNetCore": { "generateController": true, "generateDtoTypes": true, // 启用鉴别器查找 "useDiscriminatorLookup": true, // 指定鉴别器字段名 "discriminatorName": "className", // 使用默认的鉴别器值生成逻辑 "discriminatorValueGeneratorType": "Default", // 其他原有配置... } } }
如果使用OpenAPI Generator
生成后端代码时,添加额外属性来启用多态支持:
openapi-generator generate -i spec.yaml -g aspnetcore -o ./Backend --additional-properties=useDiscriminator=true,discriminatorPropertyName=className
3. 验证ASP.NET的JSON序列化配置
如果代码生成后仍然存在问题,可以手动在Program.cs中配置JsonSerializer,明确指定多态类型映射:
builder.Services.AddControllers() .AddJsonOptions(options => { // 添加枚举字符串转换器(可选,如果你有枚举类型) options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); // 配置Animal类的多态解析 options.JsonSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => { if (typeInfo.Type == typeof(Animal)) { var polymorphicInfo = typeInfo as JsonPolymorphicTypeInfo; polymorphicInfo?.DerivedTypes.Add(new JsonDerivedType(typeof(Cat), "Cat")); polymorphicInfo?.DerivedTypes.Add(new JsonDerivedType(typeof(Dog), "Dog")); } } } }; });
测试验证
用你提供的示例请求体测试:
{ "animals": [ { "id": "84d40807-4c68-4b41-9c24-619847e80269", "name": "Bob", "className": "Cat" }, { "id": "67a4b35e-4fc3-4a67-a77a-2a032640559f", "name": "Spot", "breed": "Husky", "className": "Dog" } ] }
此时后端应该能正确将第一个对象反序列化为Cat,第二个反序列化为Dog,且breed属性不会丢失。
内容的提问来源于stack exchange,提问作者Kallum Burgin
相关产品推荐
相关产品推荐

