当 POST 包含多态实体的对象映射的
@RequestBody
时,如何在 SpringBoot openapi 类型定义中定义实体继承?
设置
anyOf = { PolarParrot.class, NorwegianParrot.class}, discriminatorProperty = "parrotType"
以便键入提示必须使用哪个具体 Parrot
实例来解析 RequestBody
是否足够?
import java.lang.Override;
import java.net.URI;
import java.util.Map;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
@RestController
public class PolyParrot {
@PostMapping(value = {"/create"}, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> create(@Valid @RequestBody Flock flock) {
return ResponseEntity.created(URI.create("/flock/42")).build();
}
}
@Schema(additionalProperties = Schema.AdditionalPropertiesValue.TRUE)
class Flock {
@Schema
Map<String, Parrot> birds;
public Map<String, Parrot> getBirds() {
return birds;
}
public void setBirds(Map<String, Parrot> birds) {
this.birds = birds;
}
}
@Schema(anyOf = {
PolarParrot.class,
NorwegianParrot.class,
}, discriminatorProperty = "parrotType")
interface Parrot {
String getParrotType();
String getPlumage();
}
@Schema()
class PolarParrot implements Parrot {
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, defaultValue = "polar", example = "polar")
String parrotType;
@Override
public String getParrotType() {
return parrotType;
}
@Override
public String getPlumage() {
return "red";
}
}
@Schema()
class NorwegianParrot implements Parrot {
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, defaultValue = "norwegian", example = "norwegian")
String parrotType;
@Override
public String getParrotType() {
return parrotType;
}
@Override
public String getPlumage() {
return "blue";
}
}
根据文档和示例,似乎
anyOf
+ discriminatorProperty
应该足够了,但是,当 POST 有效负载而不是反序列化的 flock
对象时,它会抛出:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Cannot construct instance of `Parrot`
(no Creators, like default constructor, exist):
abstract types either need to be mapped to concrete types,
have custom deserializer, or contain additional type information
Parrot
还没有包含足够的“附加类型信息”吗?
我在这里错过了哪个重要部分?
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 无法构造
Parrot
的实例
(不存在像默认构造函数这样的创建者):
抽象类型要么需要映射到具体类型,
有自定义解串器,或包含附加类型信息
该错误表明,在反序列化期间,无法参考抽象类型解析有效负载中的子类型。
用此注释 Parrot 接口,并根据相应的子类在有效负载中包含关键“类型”,如下所示: