使用带有泛型的Jackson ObjectMapper到POJO而不是LinkedHashMap

Wil*_*ver 7 java json jersey jackson

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

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

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Bean是一个简单的POJO,如

public class TypeIdentifier {
    private String type;
    private Long id;
//getters/setters 
}
Run Code Online (Sandbox Code Playgroud)

整件事情可怕地打破了.它将所有内容转换为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);
        }
    }
 }
Run Code Online (Sandbox Code Playgroud)

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

Sta*_*Man 1

首先,它适用于 Long,因为它是一种本机类型,因此是 JSON 整数的默认绑定。

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

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

class MyTypeIdentifierArray extends JsonArray<TypeIdentifier> { }
Run Code Online (Sandbox Code Playgroud)

并使用该类型——事情会“正常工作”,因为超类型的通用信息总是被保留。