使用Jackson ObjectMapper和Generics到POJO而不是LinkedHashMap

使用Jersey我正在定义一项服务:

@Path("/studentIds")
public void writeList(JsonArray<Long> studentIds){
 //iterate over studentIds and save them
}

JsonArray的位置是:

public class JsonArray<T> extends ArrayList<T> {  
    public JsonArray(String v) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper(new MappingJsonFactory());
        TypeReference<ArrayList<T>> typeRef = new TypeReference<ArrayList<T>>() {};
        ArrayList<T> list = objectMapper.readValue(v, typeRef);
        for (T x : list) {
            this.add((T) x);
        }
    }
}

这很好用,但是当我做一些更复杂的事情时:

@Path("/studentIds")
public void writeList(JsonArray<TypeIdentifier> studentIds){
 //iterate over studentIds and save them by type
}

Bean是一个简单的POJO,如

public class TypeIdentifier {
    private String type;
    private Long id;
//getters/setters 
}

整件事情可怕地打破了.它将所有内容转换为LinkedHashMap而不是实际对象.如果我手动创建一个类,我可以让它工作:

public class JsonArrayTypeIdentifier extends ArrayList<TypeIdentifier> { 
    public JsonArrayTypeIdentifier(String v) throws IOException  {
        ObjectMapper objectMapper = new ObjectMapper(new MappingJsonFactory());
        TypeReference<ArrayList<TypeIdentifier>> typeRef = new TypeReference<ArrayList<TypeIdentifier>>(){};
        ArrayList<TypeIdentifier> list = objectMapper.readValue(v, typeRef);
        for(TypeIdentifier x : list){
            this.add((TypeIdentifier) x);
        }
    }
 }

但是我试图保持这个漂亮和通用,而不是添加额外的类.有关为什么只发生通用版本的任何线索?

最佳答案
首先,它适用于Longs,因为它是一种本机类型,并且作为JSON整数的默认绑定.

但至于为什么没有正确传递泛型类型信息:这很可能是由于JAX-RS API将类型传递给MessageBodyReaders和MessageBodyWriters的方式存在问题 – 传递java.lang.reflect.Type(不幸的是!)不足以传递实际的通用声明(有关这方面的更多信息,请阅读this blog entry).

一个简单的解决方法是创建辅助类型,如:

class MyTypeIdentifierArray extends JsonArray<TypeIdentifier> { }

并且使用该类型 – 事物将“正常工作”,因为始终保留超类型通用信息.

转载注明原文:使用Jackson ObjectMapper和Generics到POJO而不是LinkedHashMap - 代码日志