当使用Apache Jersey与Jackson进行JSON序列化时(在服务器和客户端上),我在反序列化通用List时遇到了问题。
我正在制作的JSON如下,“data”中的所有3个类都实现了“CheckStatusDetail”:
{
"errorCode" : 0,
"errorMessage" : null,
"type" : "array",
"data" : [ {
"@class" : "com.rrr.base.status.module.dto.DiscoveryAgentCheckStatusDetail",
"serverInfo" : {
"@class" : "com.rrr.base.util.discovery.config.xml.XMLServerInfo",
"name" : "java",
"location" : "THEO",
"description" : "sddgs",
"group" : "java",
"aliases" : [ "mercury" ]
}
}, {
"@class" : "com.rrr.base.status.module.dto.MongoDBCheckStatusDetail",
"addresses" : [ "localhost:27017" ],
"version" : "2.5",
"connected" : true
}, {
"@class" : "com.rrr.base.status.module.dto.NetworkCheckStatusDetail",
"splitBrain" : false
} ],
"count" : 3,
"status" : 0
}
生成此JSON的对象如下所示,我在客户端使用相同的类:
public class NSResponse<T> implements Serializable {
private static final long serialVersionUID = 1L;
public static final int STATUS_OK = 0;
public static final int STATUS_ERROR = -1;
public static final String TYPE_OBJECT = "object";
public static final String TYPE_ARRAY = "array";
private int status;
private int errorCode;
private String errorMessage;
private String type;
private List<T> data;
private int count;
public NSResponse() { }
public NSResponse(int errorCode, String errorMessage) {
this.status = STATUS_ERROR;
this.errorCode = errorCode;
this.errorMessage = errorMessage;
}
public NSResponse(T data) {
this.status = STATUS_OK;
this.type = TYPE_OBJECT;
this.data = new ArrayList<T>();
this.data.add(data);
this.count = this.data.size();
}
public NSResponse(List<T> data) {
this.status = STATUS_OK;
this.type = TYPE_ARRAY;
this.data = data;
this.count = (data == null) ? 0 : data.size();
}
/* Getters and setters omitted */
}
自从我将此注释添加到CheckStatusDetail接口后,正在应用@class信息:
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
public interface CheckStatusDetail extends Serializable {}
当尝试在客户端使用JSON时,我收到此错误:
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.rrr.base.status.module.dto.CheckStatusDetail
第一次尝试在反序列化后访问“数据”字段时会发生此错误。如果我调试客户端,Jackson似乎正在返回 List&lt; LinkedHashMap&gt; ,这解释了错误,因为我期待 List&lt; CheckStatusDetail&gt; 。
我做错了什么?
答案 0 :(得分:28)
你需要显示更多代码,特别是你如何调用反序列化,但是从错误中我猜你不会传递T的参数化。如果缺少,T只能被假定为Object类型,并且名义类型的Object绑定到“本机”Java类型,对于JSON对象,它是Map(具体而言,LinkedHashMap保留顺序)。
所以你可能只需要在反序列化时指定泛型类型的对象(因为运行时类型可用,所以不需要序列化);通过使用TypeReference(不是普通的Class,因为它没有泛型类型信息),或者通过构造泛型的JavaType。例如:
NSResponse<CheckStatusDetail> resp = mapper.readValue(json, new TypeReference<NSResponse<CheckStatusDetail>>() { });
或
NSResponse<CheckStatusDetail> resp = mapper.readValue(json, TypeFactory.genericType(NSResponse.class, CheckStatusDetails.class));
两个都工作;如果类型只是动态可用,则后者是必要的。