使用 Jackson 将 JSON 反序列化为 ArrayList < POJO >

我有一个 Java 类 MyPojo,我感兴趣的是从 JSON 反序列化它。我已经配置了一个特殊的 MixIn 类 MyPojoDeMixIn来帮助我进行反序列化。MyPojo只有 intString实例变量以及合适的 getter 和 setter。MyPojoDeMixIn看起来像这样:

public abstract class MyPojoDeMixIn {
MyPojoDeMixIn(
@JsonProperty("JsonName1") int prop1,
@JsonProperty("JsonName2") int prop2,
@JsonProperty("JsonName3") String prop3) {}
}

在我的测试客户机中,我执行以下操作,但是当然它在编译时不起作用,因为有一个与类型不匹配相关的 JsonMappingException

ObjectMapper m = new ObjectMapper();
m.getDeserializationConfig().addMixInAnnotations(MyPojo.class,MyPojoDeMixIn.class);
try { ArrayList<MyPojo> arrayOfPojo = m.readValue(response, MyPojo.class); }
catch (Exception e) { System.out.println(e) }

我知道我可以通过创建一个只包含 ArrayList<MyPojo>的“ Response”对象来缓解这个问题,但是之后我必须为我想要返回的每个类型创建这些有点无用的对象。

我也在网上看了看 杰克逊五分钟,但是很难理解关于 Map<A,B>的东西,以及它是如何与我的问题联系起来的。如果您看不出来,那么我对 Java 完全是新手,并且具有 Obj-C 背景。他们特别提到:

除了绑定到 POJO 和“简单”类型之外,还有一种绑定 附加变体: 绑定到通用(类型化)容器的变体。 由于所谓的类型擦除,这种情况需要特殊处理 (Java 用来实现向后兼容的泛型 方法) ,这可以防止您使用类似 Class (不编译)。

因此,如果你想把数据绑定到 Map 中,你需要使用:

Map<String,User> result = mapper.readValue(src, new TypeReference<Map<String,User>>() { });

如何直接反序列化到 ArrayList

213255 次浏览

You can deserialize directly to a list by using the TypeReference wrapper. An example method:

public static <T> T fromJSON(final TypeReference<T> type,
final String jsonPacket) {
T data = null;


try {
data = new ObjectMapper().readValue(jsonPacket, type);
} catch (Exception e) {
// Handle the problem
}
return data;
}

And is used thus:

final String json = "";
Set<POJO> properties = fromJSON(new TypeReference<Set<POJO>>() {}, json);

TypeReference Javadoc

I am also having the same problem. I have a json which is to be converted to ArrayList.

Account looks like this.

Account{
Person p ;
Related r ;


}


Person{
String Name ;
Address a ;
}

All of the above classes have been annotated properly. I have tried TypeReference>() {} but is not working.

It gives me Arraylist but ArrayList has a linkedHashMap which contains some more linked hashmaps containing final values.

My code is as Follows:

public T unmarshal(String responseXML,String c)
{
ObjectMapper mapper = new ObjectMapper();


AnnotationIntrospector introspector = new JacksonAnnotationIntrospector();


mapper.getDeserializationConfig().withAnnotationIntrospector(introspector);


mapper.getSerializationConfig().withAnnotationIntrospector(introspector);
try
{
this.targetclass = (T) mapper.readValue(responseXML,  new TypeReference<ArrayList<T>>() {});
}
catch (JsonParseException e)
{
e.printStackTrace();
}
catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}


return this.targetclass;
}

I finally solved the problem. I am able to convert the List in Json String directly to ArrayList as follows:

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


}

Another way is to use an array as a type, e.g.:

ObjectMapper objectMapper = new ObjectMapper();
MyPojo[] pojos = objectMapper.readValue(json, MyPojo[].class);

This way you avoid all the hassle with the Type object, and if you really need a list you can always convert the array to a list by:

List<MyPojo> pojoList = Arrays.asList(pojos);

IMHO this is much more readable.

And to make it be an actual list (that can be modified, see limitations of Arrays.asList()) then just do the following:

List<MyPojo> mcList = new ArrayList<>(Arrays.asList(pojos));

This variant looks more simple and elegant.

//import com.fasterxml.jackson.core.JsonProcessingException;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import com.fasterxml.jackson.databind.type.CollectionType;
//import com.fasterxml.jackson.databind.type.TypeFactory;


//import java.util.List;




CollectionType typeReference =
TypeFactory.defaultInstance().constructCollectionType(List.class, Dto.class);
List<Dto> resultDto = objectMapper.readValue(content, typeReference);

This works for me.

@Test
public void cloneTest() {
List<Part> parts = new ArrayList<Part>();
Part part1 = new Part(1);
parts.add(part1);
Part part2 = new Part(2);
parts.add(part2);
try {
ObjectMapper objectMapper = new ObjectMapper();
String jsonStr = objectMapper.writeValueAsString(parts);


List<Part> cloneParts = objectMapper.readValue(jsonStr, new TypeReference<ArrayList<Part>>() {});
} catch (Exception e) {
//fail("failed.");
e.printStackTrace();
}


//TODO: Assert: compare both list values.
}