OpenAPI YAML枚举继承实现问题:SpringBoot API序列化报错
OpenAPI生成SpringBoot REST API的StudentType层级实现与序列化问题解决
问题背景
基于OpenAPI YAML定义开发SpringBoot REST API时,生成的StudentType.java是接口,导致StudentDto无法正常序列化,调用API时抛出Jackson反序列化错误,同时需要在Swagger UI中让StudentType1和StudentType2显示为StudentType的子类型。
现有OpenAPI定义
主API YAML文件
/controller/myApi: post: tags: - ... operationId: postNewStudent requestBody: content: application/json: schema: $ref: '#/components/schemas/StudentDto' components: schemas: StudentDto: type: object properties: prop1: type: string prop2: studentType: $ref: 'common/studentSchema.yaml#/components/schemas/studentType'
common/studentSchema.yaml文件
components: schemas: studentType: type: string description: | .... oneOf: - $ref: '#/components/schemas/studentType1' - $ref: '#/components/schemas/studentType2' studentType1: type: string description: ... enum: - ENUM_VAL1_1 - ENUM_VAL1_2 studentType2: type: string description: ... enum: - ENUM_VAL2_1 - ENUM_VAL2_2
错误信息
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `...StudentDto` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer
解决方案
1. 修改OpenAPI定义,用鉴别器实现多态层级
调整studentSchema.yaml中的studentType定义,通过discriminator指定多态鉴别字段,将结构改为对象类型(string类型无法承载鉴别字段),让子类型继承父类型:
components: schemas: studentType: type: object description: 学生类型父类 discriminator: propertyName: type mapping: TYPE1: '#/components/schemas/studentType1' TYPE2: '#/components/schemas/studentType2' required: - type properties: type: type: string description: 类型标识,用于区分不同子类型 oneOf: - $ref: '#/components/schemas/studentType1' - $ref: '#/components/schemas/studentType2' studentType1: allOf: - $ref: '#/components/schemas/studentType' - type: object properties: value: type: string description: studentType1枚举值 enum: - ENUM_VAL1_1 - ENUM_VAL1_2 required: - value studentType2: allOf: - $ref: '#/components/schemas/studentType' - type: object properties: value: type: string description: studentType2枚举值 enum: - ENUM_VAL2_1 - ENUM_VAL2_2 required: - value
修改后,OpenAPI Generator会生成抽象父类StudentType,以及继承它的StudentType1和StudentType2子类,Jackson可通过type字段自动识别并反序列化对应子类。
2. 配置OpenAPI Generator生成抽象类而非接口
若希望保留原有string enum结构,可通过生成器配置让oneOf生成抽象类而非接口:
- Maven配置:在
pom.xml的openapi-generator-maven-plugin中添加参数:
<plugin> <groupId>org.openapitools</groupId> <artifactId>openapi-generator-maven-plugin</artifactId> <version>最新版本</version> <executions> <execution> <goals> <goal>generate</goal> </goals> <configuration> <!-- 其他配置 --> <configOptions> <abstractClassForOneOf>true</abstractClassForOneOf> <interfaceOnly>false</interfaceOnly> </configOptions> </configuration> </execution> </executions> </plugin>
- Gradle配置:在
build.gradle中添加:
openapiGenerate { // 其他配置 configOptions = [ abstractClassForOneOf: "true", interfaceOnly: "false" ] }
同时在application.yml中配置Jackson支持多态反序列化:
spring: jackson: deserialization: fail-on-unknown-properties: false polymorphism: type-id-resolver: com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator
3. 确保Swagger UI显示子类型
上述两种修改方式都会让Swagger UI自动识别oneOf与discriminator的关联关系,在StudentDto的Schema中展示StudentType的子类型选项,支持用户选择具体子类型结构。
内容的提问来源于stack exchange,提问作者blaiso
相关产品推荐
相关产品推荐

