Java 使用JSON-B/Yasson将JSON反序列化为多态POJO
我在一个资源类中有一个补丁端点,其中有一个抽象类作为请求主体。 我得到以下错误:Java 使用JSON-B/Yasson将JSON反序列化为多态POJO,java,resteasy,quarkus,jsonb-api,yasson,Java,Resteasy,Quarkus,Jsonb Api,Yasson,我在一个资源类中有一个补丁端点,其中有一个抽象类作为请求主体。 我得到以下错误: 22:59:30 SEVERE [or.ec.ya.in.Unmarshaller] (on Line: 64) (executor-thread-63) Can't create instance 因为我声明为参数的身体模型是抽象的,所以它无法反序列化 我希望得到元素A或元素B 如何声明主体是多态的 这是元素层次结构 public abstract class BaseElement { public
22:59:30 SEVERE [or.ec.ya.in.Unmarshaller] (on Line: 64) (executor-thread-63) Can't create instance
因为我声明为参数的身体模型是抽象的,所以它无法反序列化
我希望得到元素A或元素B
如何声明主体是多态的
这是元素层次结构
public abstract class BaseElement {
public String name;
public Timestamp start;
public Timestamp end;
}
public class Element_A extends BaseElement{
public String A_data;
}
public class Element_B extends BaseElement{
public long B_data;
}
这是具有我的端点的资源类
@Path("/myEndpoint")
public class ResourceClass {
@PATCH
@Path("/{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public Response updateEvent(@Valid BaseElement element, @Context UriInfo uriInfo, @PathParam long id) {
if (element instanceof Element_A) {
// Element_A logic
} else if (element instanceof Element_B) {
// Element_B logic
}
return Response.status(Response.Status.OK).entity("working").type(MediaType.TEXT_PLAIN).build();
}
}
这是我发送补丁请求的请求主体
{
"name": "test",
"startTime": "2020-02-05T17:50:55",
"endTime": "2020-02-05T17:51:55",
"A_data": "it's my data"
}
我还尝试添加@JsonbTypeDeserializer和一个自定义的反序列化程序,但没有成功
@JsonbTypeDeserializer(CustomDeserialize.class)
public abstract class BaseElement {
public String type;
public String name;
public Timestamp start;
public Timestamp end;
}
抛出此错误:
02:33:10 SEVERE [or.ec.ya.in.Unmarshaller] (executor-thread-67) null
02:33:10 SEVERE [or.ec.ya.in.Unmarshaller] (executor-thread-67) Internal error: null
My pom.xml包括:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jsonb</artifactId>
</dependency>
夸克斯
夸克斯轻松
夸克斯
quarkus resteasy jsonb
JSON-B还没有对多态反序列化的理想支持,所以现在您最多可以做一些变通。我们这里有一个设计问题有待解决:,所以请给它一个+1
您对自定义反序列化程序的想法是正确的,但问题是您无法解析当前的JsonObject
,然后用同一个解析器调用context.deserialize()
,因为解析器已经超过了读取JSON对象的状态。(JSONParser是一个只向前的解析器,因此没有“倒带”它的方法)
因此,您仍然可以在自定义反序列化程序中调用parser.getObject()
,但在确定特定JSON字符串的具体类型后,需要使用单独的Jsonb
实例来解析该字符串
公共静态类CustomDeserialize实现JsonbDeserializer{
私有静态final Jsonb Jsonb=JsonbBuilder.create();
@凌驾
公共BaseElement反序列化(JsonParser解析器,反序列化上下文,类型rtType){
JsonObject jsonObj=parser.getObject();
字符串jsonString=jsonObj.toString();
字符串类型=jsonObj.getString(“类型”);
开关(类型){
案例“A”:
返回jsonb.fromJson(jsonString,Element_A.class);
案例“B”:
返回jsonb.fromJson(jsonString,Element_B.class);
违约:
抛出新的JSONBEException(“未知类型:+类型”);
}
}
}
旁注:您需要将基本对象模型更改为以下内容:
@JsonbTypeDeserializer(CustomDeserialize.class)
公共抽象静态类BaseElement{
公共字符串类型;
公共字符串名称;
@JsonbProperty(“开始时间”)
公共LocalDateTime启动;
@JsonbProperty(“结束时间”)
公共LocalDateTime结束;
}
start
和end
)以匹配JSON字段名(startTime
和endTime
),也可以使用@JsonbProperty
注释重新映射它们(我在上面已经做过)java.TIME.LocalDateTime
而不是java.sql.Timestamp
,因为LocalDateTime
处理时区,但考虑到您提供的示例数据,这两种方法最终都可以工作02:33:10 SEVERE [or.ec.ya.in.Unmarshaller] (executor-thread-67) null
02:33:10 SEVERE [or.ec.ya.in.Unmarshaller] (executor-thread-67) Internal error: null
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jsonb</artifactId>
</dependency>