美文网首页Jackson学习笔记
Jackson –反序列化为数组或集合

Jackson –反序列化为数组或集合

作者: 攻城狮susht | 来源:发表于2020-05-08 16:28 被阅读0次

1.概述

本文主要展示如何使用Jackson 2将JSON数组反序列化为Java数组或集合

要了解更多关于Jackson的用法,请移步Jackson系列文章

2.反序列化为数组

Jackson很容易将JSON字符串反序列化为Java数组:

    @Test //json字符串转换为数组
    public void  jsonStringToArray() throws JsonProcessingException {
        //创建ObjectMapper对象
        ObjectMapper mapper=new ObjectMapper();
        String json="[\"C\",\"C++\",\"Java\",\"Python\",\"Golang\",\"JavaScript\"]";
        String[] array= mapper.readValue(json,String[].class);
        for (String str:array) {
            System.out.println(str);
        }
    }

    @Test //json数组反序列化为数组对象
    public final void jsonStringToArrayObject() throws JsonProcessingException {
         ObjectMapper mapper = new ObjectMapper();
         List<MyDto> listOfDtos = Lists.newArrayList(new MyDto("a", 1, true), 
                                                     new MyDto("bc", 3, false));
         String jsonArray = mapper.writeValueAsString(listOfDtos);
         System.out.println(jsonArray);
         MyDto[] asArray = mapper.readValue(jsonArray, MyDto[].class);
         assertThat(asArray[0], instanceOf(MyDto.class));
         System.out.println(asArray.length);
         System.out.println(asArray[0]);
    }

3.反序列化为集合

将相同的JSON数组反序列化为Java集合要复杂一些。默认情况下,Jackson无法获取完整的泛型类型信息,而是将JSON数组反序列化为一个Linked HashMap实例的集合。转换不会出现错误,但是获取具体数据时会抛出异常。

    @Test //json数组反序列化为List对象
    public  void jsonStringToListObject() throws JsonProcessingException {
         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);
         System.out.println(asList.get(0));
         //获取对象具体值时抛出异常
         System.out.println(asList.get(0).getStringValue());
    }

抛出异常如下:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.wxbsusht.jackson.tocollection.MyDto

有两种方法可以使Jackson理解正确的类型信息 。 第一种时Jackson库提供的TypeReference

    @Test
    public void jsonStringToListObjectByTypeReference() throws JsonProcessingException {
         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));
         System.out.println(asList.get(0));
         //获取正确结果
         System.out.println(asList.get(0).getStringValue());
    }

另外一种是使用重载的readValue方法来接受JavaType:

    @Test
    public  void jsonStringToListObjectByCollectionType() throws JsonProcessingException {
         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));
         System.out.println(asList.get(0));
         //获取正确结果
         System.out.println(asList.get(0).getStringValue());
    }

最后一点需要注意的是,MyDto类需要有一个无参数的默认构造函数——如果没有,则Jackson将无法实例化它

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.wxbsusht.jackson.tocollection.MyDto` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

对于带有泛型的对象反序列化时,可以使用TypeReference

public class Pager<T> {
    private Integer totalCount;
    private Integer currentPage;
    private List<T> datas;
 }

其中User类需要有一个无参数的默认构造函数——如果没有,则Jackson将无法实例化它

@Test
public  void jsonStringToListObjectByGeneric() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    List<User> userList = Lists.newArrayList(new User("jack", 25),
            new User("tom", 3));
    Pager<User> pager=new Pager<>();
    pager.setCurrentPage(2);
    pager.setTotalCount(200);
    pager.setDatas(userList);
    String jsonString = mapper.writeValueAsString(pager);
    System.out.println(jsonString);

    Pager<User> userPager = mapper.readValue(jsonString, new TypeReference< Pager<User>>() {});

    System.out.println(userPager);
    //获取正确结果
    // Pager{totalCount=200, currentPage=2, datas=[User{name='jack', age=25}, User{name='tom', age=3}]}
}

4. 结论

将JSON数组映射到java集合是Jackson最常用的功能之一,这些解决方案对于实现正确的、类型安全的映射至关重要。

相关文章

网友评论

    本文标题:Jackson –反序列化为数组或集合

    本文链接:https://www.haomeiwen.com/subject/pvwaghtx.html