Jackson 反序列化数组类型json值
本文介绍如何使用Jackson 2反序列化json数组值至Java 数组或集合。
反序列化为Array
Jackson可以很容易反序列化为Java数组:
@Test
public void givenJsonArray_whenDeserializingAsArray_thenCorrect()
throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
List<MyDto> listOfDtos = Lists.newArrayList(
new MyDto("a", 1, true), new MyDto("bc", 3, false));
String jsonArray = mapper.writeValueAsString(listOfDtos);
// [{"stringValue":"a","intValue":1,"booleanValue":true},
// {"stringValue":"bc","intValue":3,"booleanValue":false}]
MyDto[] asArray = mapper.readValue(jsonArray, MyDto[].class);
assertThat(asArray[0], instanceOf(MyDto.class));
}
反序列化为List
相比于数组,转Java Collection要稍微复杂点,缺省情况下Jackson不能获得完整的泛型信息,需要创建LinkedHashMap实例:
@Test
public void givenJsonArray_whenDeserializingAsListWithNoTypeInfo_thenNotCorrect()
throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
List<MyDto> listOfDtos = Lists.newArrayList(
new MyDto("a", 1, true), new MyDto("bc", 3, false));
String jsonArray = mapper.writeValueAsString(listOfDtos);
List<MyDto> asList = mapper.readValue(jsonArray, List.class);
assertThat((Object) asList.get(0), instanceOf(LinkedHashMap.class));
}
有两种方法能帮助Jackson理解右边类型信息,使用Jackson提供的TypeReference实现:
@Test
public void givenJsonArray_whenDeserializingAsListWithTypeReferenceHelp_thenCorrect()
throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
List<MyDto> listOfDtos = Lists.newArrayList(
new MyDto("a", 1, true), new MyDto("bc", 3, false));
String jsonArray = mapper.writeValueAsString(listOfDtos);
List<MyDto> asList = mapper.readValue(
jsonArray, new TypeReference<List<MyDto>>() { });
assertThat(asList.get(0), instanceOf(MyDto.class));
}
或者能使用接收JavaType类型的重载readValue方法:
@Test
publi void givenJsonArray_whenDeserializingAsListWithJavaTypeHelp_thenCorrect()
throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
List<MyDto> listOfDtos = Lists.newArrayList(
new MyDto("a", 1, true), new MyDto("bc", 3, false));
String jsonArray = mapper.writeValueAsString(listOfDtos);
CollectionType javaType = mapper.getTypeFactory()
.constructCollectionType(List.class, MyDto.class);
List<MyDto> asList = mapper.readValue(jsonArray, javaType);
assertThat(asList.get(0), instanceOf(MyDto.class));
}
分为两步实现,首先 mapper.getTypeFactory().constructCollectionType(List.class, MyDto.class)
获得CollectionType,然后调用readValue方法返回正确的类型列表对象。
最后需要说明的是MyDto类需要有缺省无参构造函数,否则Jackson实例化失败,错误信息如下:
com.fasterxml.jackson.databind.JsonMappingException:
No suitable constructor found for type [simple type, class org.baeldung.jackson.ignore.MyDto]:
can not instantiate from JSON object (need to add/enable type information?)
总结
将JSON数组映射到java集合是Jackson最常用的任务之一,关键是如何实现正确、类型安全的映射。
本文参考链接:https://blog.csdn.net/neweastsun/article/details/100171174