杰克逊和泛型类型引用

2022-08-31 07:51:02

我想使用jackson json库作为泛型方法,如下所示:

public MyRequest<T> tester() {
    TypeReference<MyWrapper<T>> typeRef = new TypeReference<MyWrapper<T>>();  
    MyWrapper<T> requestWrapper = (MyWrapper<T>) JsonConverter.fromJson(jsonRequest, typeRef);
    return requestWrapper.getRequest();
}
public class MyWrapper<T> {

    private MyRequest<T> request;

    public MyRequest<T> getRequest() {
        return request;
    }

    public void setRequest(MyRequest<T> request) {
        this.request = request;
    }
}
public class MyRequest<T> {
     private List<T> myobjects;
        
     public void setMyObjects(List<T> ets) {
         this.myobjects = ets;
     }

     @NotNull
     @JsonIgnore
     public T getMyObject() {
         return myobjects.get(0);
     }
}

现在的问题是,当我调用请求对象内的getMyObject()时,Jackson会将嵌套的自定义对象作为LinkedHashMap返回。有没有办法指定需要返回 T 对象?例如:如果我发送了客户类型的对象,那么客户应该从该列表中返回吗?


答案 1

这是 Java 类型擦除的一个众所周知的问题:T 只是一个类型变量,您必须指示实际的 class,通常作为 Class 参数。没有这些信息,最好的办法是使用边界;而普通的 T 与“T 扩展对象”大致相同。然后,Jackson 会将 JSON 对象绑定为 Maps。

在这种情况下,测试器方法需要有权访问类,并且您可以构造

JavaType type = mapper.getTypeFactory().
  constructCollectionType(List.class, Foo.class)

然后

List<Foo> list = mapper.readValue(new File("input.json"), type);

答案 2

“JavaType”工作原理!!我试图将json String中的List解组(反序列化)到ArrayList java对象,并且一直在努力寻找解决方案。
下面是最终给我解决方案的代码。法典:

JsonMarshallerUnmarshaller<T> {
    T targetClass;

    public ArrayList<T> unmarshal(String jsonString) {
        ObjectMapper mapper = new ObjectMapper();

        AnnotationIntrospector introspector = new JacksonAnnotationIntrospector();
        mapper.getDeserializationConfig()
            .withAnnotationIntrospector(introspector);

        mapper.getSerializationConfig()
            .withAnnotationIntrospector(introspector);
        JavaType type = mapper.getTypeFactory().
            constructCollectionType(
                ArrayList.class, 
                targetclass.getClass());

        try {
            Class c1 = this.targetclass.getClass();
            Class c2 = this.targetclass1.getClass();
            ArrayList<T> temp = (ArrayList<T>) 
                mapper.readValue(jsonString,  type);
            return temp ;
        } catch (JsonParseException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null ;
    }  
}