1. 概述
本教程将展示如何使用Jackson 2将JSON数组反序列化为Java数组或集合。
如果你希望深入了解Jackson 2的其他酷炫功能,可以访问Jackson 2教程。
2. 反序列化到数组
Jackson可以轻松地将JSON反序列化为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));
}
3. 反序列化到集合
将相同的JSON数组读入Java集合稍微困难一些 - 默认情况下,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理解正确的类型信息:我们可以使用库提供的专门为此目的的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
public 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));
}
最后一点是,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?)
另一种选择是使用@JsonCreator
注解来调整反序列化的构造函数。
4. 总结
将JSON数组映射到Java集合是Jackson常用于的任务之一,这些解决方案对于实现正确、类型安全的映射至关重要。
所有示例和代码片段的实现可以在我们的GitHub项目中找到 - 这是一个基于Maven的项目,导入并运行非常方便。