杰克逊和泛型类型参考

tec*_*zen 96 java generics json jackson

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

...

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{
     private List<T> myobjects;

     public void setMyObjects(List<T> ets) {
         this.myobjects = ets;
     }

     @NotNull
     @JsonIgnore
     public T getMyObject() {
         return myobjects.get(0);
     }
}
Run Code Online (Sandbox Code Playgroud)

现在的问题是,当我调用请求对象内的getMyObject()时,jackson将嵌套的自定义对象作为LinkedHashMap返回.有没有什么方法可以指定需要返回T对象?例如:如果我发送了Customer类型的对象,那么应该从该列表返回Customer?

谢谢.

Sta*_*Man 174

这是Java类型擦除的一个众所周知的问题:T只是一个类型变量,你必须指出实际的类,通常是Class参数.没有这些信息,最好的办法是使用边界; 和普通T大致相同'T extends Object'.然后杰克逊将JSON对象绑定为地图.

在这种情况下,tester方法需要访问Class,并且您可以构造

JavaType type = mapper.getTypeFactory().
  constructCollectionType(List.class, Foo.class)
Run Code Online (Sandbox Code Playgroud)

然后

List<Foo> list = mapper.readValue(new File("input.json"), type);
Run Code Online (Sandbox Code Playgroud)

  • 它工作正常:我做了以下内容:JavaType topMost = mapper.getTypeFactory().constructParametricType(MyWrapper.class,ActualClassRuntime.class); 然后做了readValue,它终于奏效了:) (13认同)
  • @husayt 是的,从技术上讲,java-classmate lib 更胜一筹。但是将它与 Jackson 集成有点棘手,因为 Jackson 自己的类型抽象是 API 的集成部分。从长远来看,找出让杰克逊使用同学代码的正确方法会很棒,无论是嵌入的还是通过 dep 的。 (2认同)
  • 我觉得杰克逊不应该必须掩盖仿制药中感觉上的空白,但无论哪种方式,它都做得很好。 (2认同)

小智 6

'JavaType'有效!! 我试图将json String中的List解组(反序列化)到ArrayList java Objects,并且几天来一直在努力寻找解决方案.
下面是最终给我解决方案的代码.码:

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

  • 如何初始化TargetClass? (2认同)