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();
}
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 对象吗?例如: 如果我发送类型为 Customer 的对象,那么 Customer 应该从该 List 返回?

208049 次浏览

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

在这种情况下,测试人员方法需要访问 Class,您可以构造

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

然后

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

“ 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 ;
}
}

我修改了 Rushidesai1的回答以包含一个工作示例。

JsonMarshall 爪哇

import java.io.*;
import java.util.*;


public class JsonMarshaller<T> {
private static ClassLoader loader = JsonMarshaller.class.getClassLoader();


public static void main(String[] args) {
try {
JsonMarshallerUnmarshaller<Station> marshaller = new JsonMarshallerUnmarshaller<>(Station.class);
String jsonString = read(loader.getResourceAsStream("data.json"));
List<Station> stations = marshaller.unmarshal(jsonString);
stations.forEach(System.out::println);
System.out.println(marshaller.marshal(stations));
} catch (IOException e) {
e.printStackTrace();
}
}


@SuppressWarnings("resource")
public static String read(InputStream ios) {
return new Scanner(ios).useDelimiter("\\A").next(); // Read the entire file
}
}

输出

Station [id=123, title=my title, name=my name]
Station [id=456, title=my title 2, name=my name 2]
[{"id":123,"title":"my title","name":"my name"},{"id":456,"title":"my title 2","name":"my name 2"}]

JsonMarshallerUnmaraller.java

import java.io.*;
import java.util.List;


import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;


public class JsonMarshallerUnmarshaller<T> {
private ObjectMapper mapper;
private Class<T> targetClass;


public JsonMarshallerUnmarshaller(Class<T> targetClass) {
AnnotationIntrospector introspector = new JacksonAnnotationIntrospector();


mapper = new ObjectMapper();
mapper.getDeserializationConfig().with(introspector);
mapper.getSerializationConfig().with(introspector);


this.targetClass = targetClass;
}


public List<T> unmarshal(String jsonString) throws JsonParseException, JsonMappingException, IOException {
return parseList(jsonString, mapper, targetClass);
}


public String marshal(List<T> list) throws JsonProcessingException {
return mapper.writeValueAsString(list);
}


public static <E> List<E> parseList(String str, ObjectMapper mapper, Class<E> clazz)
throws JsonParseException, JsonMappingException, IOException {
return mapper.readValue(str, listType(mapper, clazz));
}


public static <E> List<E> parseList(InputStream is, ObjectMapper mapper, Class<E> clazz)
throws JsonParseException, JsonMappingException, IOException {
return mapper.readValue(is, listType(mapper, clazz));
}


public static <E> JavaType listType(ObjectMapper mapper, Class<E> clazz) {
return mapper.getTypeFactory().constructCollectionType(List.class, clazz);
}
}

站,爪哇

public class Station {
private long id;
private String title;
private String name;


public long getId() {
return id;
}


public void setId(long id) {
this.id = id;
}


public String getTitle() {
return title;
}


public void setTitle(String title) {
this.title = title;
}


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


@Override
public String toString() {
return String.format("Station [id=%s, title=%s, name=%s]", id, title, name);
}
}

Data Json

[{
"id": 123,
"title": "my title",
"name": "my name"
}, {
"id": 456,
"title": "my title 2",
"name": "my name 2"
}]