在Apache Jackson和Jackson一起使用Apache Jersey进行JSON序列化时(在服务器和客户端上),在反序列化通用List时遇到问题。
我正在生成的JSON如下,“数据”中的所有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 ,该错误将得到解释,因为我期望使用 List 。
我究竟做错了什么?
您需要显示更多代码,特别是有关如何调用反序列化的代码,但是从错误中我想您可能没有传递T的参数化。如果丢失了T,则只能假定T的类型为Object,标称类型为T。对象绑定到“本机” Java类型,对于JSON对象,它是Map(特别是LinkedHashMap以保留顺序)。
因此,您可能只需要在反序列化时指定对象的通用类型(对于序列化,由于可以使用运行时类型,因此不需要);通过使用TypeReference(不是普通类,因为它没有泛型类型信息),或通过构造启用了泛型的JavaType来实现。例如:
NSResponse<CheckStatusDetail> resp = mapper.readValue(json, new TypeReference<NSResponse<CheckStatusDetail>>() { });
要么
NSResponse<CheckStatusDetail> resp = mapper.readValue(json, TypeFactory.genericType(NSResponse.class, CheckStatusDetails.class));
两者都起作用;如果type仅动态可用,则后者是必需的。