2011-05-19 71 views
16

在使用JSON序列化的JSON序列化时(在服务器和客户端上)使用Apache Jersey时,我在解串列表中遇到问题。Jackson不反序列化它已经序列化的通用列表

我生产的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看起来像这样的对象,我使用同一个类客户端:

@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class") 
public interface CheckStatusDetail extends Serializable {} 

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信息

当试图消耗在客户端的JSON,我得到这个错误:发生

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.rrr.base.status.module.dto.CheckStatusDetail 

这个错误我第一次尝试deserialising之后进入“数据”字段。如果我调试客户端,杰克逊似乎返回列表< LinkedHashMap的>,这也解释了错误,因为我期待一个列表<CheckStatusDetail>

我在做什么错?

回答

28

你需要显示更多的代码,特别是你如何调用反序列化,但从错误我猜你没有通过T的参数化。如果缺少,T只能被认为是Object类型,而名义类型的Object绑定到“本地”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)); 

两个工作;后者是必要的,如果类型只是动态可用。

+0

非常好,我不得不以一种稍微不同的方式使用TypeFactory:“TypeFactory.type(NSResponse.class,CheckStatusDetails.class)”,但可能是版本不匹配,结果正是我想要的。谢谢! – seanhodges 2011-05-24 16:23:24

+1

是的,我没有检查确切的方法名称(加1.8确实有轻微的变化),但重要的是你得到它的工作。 :) – StaxMan 2011-05-24 21:04:52

+1

@seanhodges TypeFactory.type已弃用使用? – kamaci 2011-11-15 08:35:41