Skip to main content
 首页 » 编程设计

Jackson 反序列化数组类型json值

2022年07月19日121飞鱼

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