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

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最常用的功能之一,这些解决方案对于实现正确的、类型安全的映射至关重要。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350