jackson - Swagger oneOf 类型:Jackson 试图实例化接口而不是实现?
问题描述
我正在使用该oneOf
功能定义几个可能的模式,这些模式可以进入我的服务的请求正文属性。在生成的 Java 客户端代码中,这些模式的 Java 实现实现了一个接口,但是当我通过发送请求时,Jackson 正在尝试创建接口的实例,而不是具体的类。
Swagger-codegen 版本
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>3.0.14</version>
Swagger 声明文件内容
schemas:
TestRequest:
description:
Test request
type:
object
required:
- criteria
properties:
criteria:
oneOf:
- $ref: '#/components/schemas/CriteriaA'
- $ref: '#/components/schemas/CriteriaB'
...
CriteriaA:
description: Criteria A
type: object
required:
- type
- query
properties:
type:
description: A description
type: string
enum:
- CriteriaA
query:
description: A query.
type: object
重现步骤
swagger codegen 生成的 Java 客户端代码如下所示:
界面:
public interface OneOfTestRequestCriteria {}
具体类:
@Schema(description = "")
@javax.annotation.Generated(value = "io.swagger.codegen.v3.generators.java.JavaClientCodegen", date = "2020-01-28T13:06:29.942Z[Europe/London]")
public class CriteriaA implements OneOfTestRequestCriteria {
@JsonAdapter(TypeEnum.Adapter.class)
public enum TypeEnum {
CriteriaA("CriteriaA");
private String value;
TypeEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
@Override
public String toString() {
return String.valueOf(value);
}
public static TypeEnum fromValue(String text) {
for (TypeEnum b : TypeEnum.values()) {
if (String.valueOf(b.value).equals(text)) {
return b;
}
}
return null;
}
public static class Adapter extends TypeAdapter<TypeEnum> {
@Override
public void write(final JsonWriter jsonWriter, final TypeEnum enumeration) throws IOException {
jsonWriter.value(enumeration.getValue());
}
@Override
public TypeEnum read(final JsonReader jsonReader) throws IOException {
String value = jsonReader.nextString();
return TypeEnum.fromValue(String.valueOf(value));
}
}
} @SerializedName("type")
private TypeEnum type = null;
@SerializedName("query")
private Object query = null;
public CriteriaA type(TypeEnum type) {
this.type = type;
return this;
}
@Schema(required = true, description = "")
public TypeEnum getType() {
return type;
}
public void setType(TypeEnum type) {
this.type = type;
}
public CriteriaA query(Object query) {
this.query = query;
return this;
}
@Schema(required = true, description = "")
public Object getQuery() {
return query;
}
public void setQuery(Object query) {
this.query = query;
}
@Override
public boolean equals(java.lang.Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
CriteriaA criteriaA = (CriteriaA ) o;
return Objects.equals(this.type, criteriaA.type) &&
Objects.equals(this.query, criteriaA.query);
}
@Override
public int hashCode() {
return Objects.hash(type, query);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class CriteriaA {\n");
sb.append(" type: ").append(toIndentedString(type)).append("\n");
sb.append(" query: ").append(toIndentedString(query)).append("\n");
sb.append("}");
return sb.toString();
}
private String toIndentedString(java.lang.Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}
我正在尝试使用此生成的客户端代码发送请求:
final TestRequest testRequest = new TestRequest();
final CriteriaA criteriaA = new CriteriaA ();
criteriaA .setType(CriteriaA .TypeEnum.CriteriaA);
criteriaA .setQuery("a query");
testRequest .setCriteria(criteriaA );
final ApiResponse<Void> apiResponse = testApi.createOrUpdateTestWithHttpInfo(testRequest);
当杰克逊试图反序列化它时,运行上面的客户端代码会导致这个错误。似乎是在尝试构造接口 OneOfTestRequestCriteria 的实例,而不是接口的具体实现;标准A:
[请求处理失败;嵌套异常是org.springframework.http.converter.HttpMessageConversionException:类型定义错误:[简单类型,类com.acme.tag.models.OneOfTestRequestCriteria];嵌套异常是 com.fasterxml.jackson.databind.exc.InvalidDefinitionException:无法构造 com.acme.tag.models.OneOfTestRequestCriteria 的实例(不存在像默认构造那样的创建者):抽象类型要么需要映射到具体类型,具有自定义反序列化器,或包含其他类型信息\n
如果我注释生成的界面:
public interface OneOfTestRequestCriteria {}
具有以下内容:
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@Type(value = CriteriaA.class, name = "CriteriaA")
})
public interface OneOfTestRequestCriteria {
}
然后请求被正确地反序列化为 CriteriaA - 我是否在我的 swagger.yaml 中遗漏了一些内容,这会导致该接口没有被 codegen 工具注释?
解决方案
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>3.0.18</version>
另请参阅:https ://github.com/swagger-api/swagger-codegen-generators/pull/585
推荐阅读
- java - GSon 嵌套无名数组
- java - 使用 Spring Framework 的 Java 应用程序无法在 WebSphere 9.0.0.4 上启动
- bash - 在 bash 函数中使用管道和 egrep
- javascript - 在Javascript中检测unicode删除线字符
- android - 在 Android 中通过蓝牙发送文件
- python - 如何在 python 中从 yaml 中选择特定属性
- parallel-processing - 写入单个向量时 OpenMP 中的错误共享
- javascript - JavaScript 连接嵌套对象扩展运算符
- mqtt - MQTT:使用标准输入的 mosquitto_pub 发布多个主题
- javascript - 想知道在创建服务器和路由时构建 URL 是如何工作的。也想知道 => 命令