GSON使用笔记(3) -- 如何反序列化出List

本文通过3个问题来讨论如何使用GSON把JSON反序列化为List。

问题1

有这样两个类:

class MyObj {
    int x;
}

class MyList {
    List<MyObj> objList = new LinkedList<>();
}

那下面的测试能通过吗?

    @Test
    public void test1() {
        MyList myList = new Gson().fromJson("{objList:[]}", MyList.class);
        Assert.assertEquals(LinkedList.class, myList.objList.getClass());
    }

答案1

答案是,测试通不过!原因是GSON不知道objList的具体类型,因此只能选择默认的ArrayList。更详细的解释,可以参考这篇文章和ConstructorConstructor类的源代码。如果确实想让GSON创建LinkedList实例该怎么办呢?也简单,就是给objList一个更具体的类型:

class MyList {
    LinkedList<MyObj> objList = new LinkedList<>();
}

问题2

下面的测试能通过吗?

    @Test
    public void test2() {
        ArrayList<?> list = new Gson().fromJson("[{x:1}]", ArrayList.class);
        Assert.assertEquals(1, list.size());
        Assert.assertEquals(MyObj.class, list.get(0).getClass());
    }

答案2

很明显,不能。因为fromJson方法不能从"[{x:1}]"参数推测出数组里放的是MyObj类型的对象,也无法从ArrayList.class参数得到这个信息。那么改成下面这样呢?

ArrayList<MyObj> list = new Gson().fromJson("[{x:1}]", ArrayList<MyObj>.class);

更糟糕,连编译都无法通过!因为Java的泛型是用擦拭法实现的,说白了只是编译器提供给程序员的语法糖,根本不存在ArrayList<MyObj>这样一个类。那么怎样才能让GSON反序列化出我们想要的泛型对象呢?答案是,请TypeToken帮忙:

    @Test
    public void test3() {
        Type type = new TypeToken<ArrayList<MyObj>>() {}.getType();
        ArrayList<MyObj> list = new Gson().fromJson("[{x:1}]", type);
        Assert.assertEquals(1, list.size());
        Assert.assertEquals(MyObj.class, list.get(0).getClass());
    }

GSON提供了TypeToken这个类来帮助我们捕获(capture)像ArrayList<MyObj>这样的泛型信息。test3()的第一行代码创建了一个匿名内部类,这样,Java编译器就会把泛型信息编译到这个匿名内部类里,然后在运行时就可以被getType()方法用反射API提取到。

问题3

如果我想写一个通用的方法,把json反序列化成List,下面这个方法可行吗?

    public static <T> ArrayList<T> jsonToList(String json, Class<T> classOfT) {
        Type type = new TypeToken<ArrayList<T>>() {}.getType();
        return new Gson().fromJson(json, type);
    }

这个测试能通过吗?

    @Test
    public void test4() {
        ArrayList<MyObj> list = jsonToList("[{x:1}]", MyObj.class);
        Assert.assertEquals(1, list.size());
        Assert.assertEquals(MyObj.class, list.get(0).getClass());
    }

答案3

答案是,方法不可行(虽然能编译通过),测试通不过!还是因为Java泛型的擦除法,详细的回答可以看stackoverflow上的这个问题。那还有办法实现jsonToList()这个通用方法呢?有的,只是稍微复杂一点:

    public static <T> ArrayList<T> jsonToList(String json, Class<T> classOfT) {
        Type type = new TypeToken<ArrayList<JsonObject>>(){}.getType();
        ArrayList<JsonObject> jsonObjs = new Gson().fromJson(json, type);

        ArrayList<T> listOfT = new ArrayList<>();
        for (JsonObject jsonObj : jsonObjs) {
            listOfT.add(new Gson().fromJson(jsonObj, classOfT));
        }

        return listOfT;
    }

分两步,先反序列化出ArrayList<JsonObject>,然后在一个个的把JsonObject转成classOfT类型的对象。

GSON使用笔记(3) -- 如何反序列化出List

时间: 2024-08-06 23:40:58

GSON使用笔记(3) -- 如何反序列化出List的相关文章

.net学习笔记--序列化与反序列化

序列化其实就是将一个对象的所有相关的数据保存为一个二进制文件(注意:是一个对象) 而且与这个对象相关的所有类型都必须是可序列化的所以要在相关类中加上 [Serializable]特性 对象类型包括:对象本神包含的类型,父类 拥有需要的对象之后:1.将对象转换为二进制数据 使用专门的对像进行转换 BinaryFormatter 2.将二进制数据写入到文件 FileSteam 反序列化则是把二进制文件转换为一个对象 例子代码如下: 1 using System; 2 using System.Col

Android Gson使用笔记

最近在做一个java web service项目,需要用到jason,本人对java不是特别精通,于是开始搜索一些java平台的json类库. 发现了google的gson,因为之前对于protocolbuf有一些了解,带着一些好奇心,我开始使用了gson. 经过比较,gson和其他现有java json类库最大的不同时gson需要序列化得实体类不需要使用annotation来标识需要序列化得字段,同时gson又可以通过使用annotation来灵活配置需要序列化的字段. 下面是一个简单的例子:

Json工具类库之Gson实战笔记

日常接口的数据传输通常使用xml或者json来传递数据,xml较庞大但是描述数据能力十分出众,json数据结构较小而且支持ajax传输,xml在数据传输和解析资源占用都比较逊色于json.因此日常的接口通常都使用json的数据格式进行传输.一方面能减少应用或者客户端如Android应用解析数据的资源占用,另一方面节省宝贵的数据传输时间. Java中对Json的序列化和反序列化常用的工具有Json.Fastjson.Gson等.其中,Fastjson是阿里巴巴的开源产品,用Java语言实现,号称是

GSON使用笔记(1) -- 序列化时排除字段的几种方式

http://blog.csdn.net/zxhoo/article/details/21471005 GSON是Google发布的JSON序列化/反序列化工具,非常容易使用.本文简要讨论在使用GSON将Java对象转成JSON时,如何排除某些字段. 最简单的用法 假设有下面这个类: [java] view plain copy class MyObj { public int x; public int y; public MyObj(int x, int y) { this.x = x; t

Java学习笔记——序列化和反序列化

寒雨连江夜入吴,平明送客楚山孤. 洛阳亲友如相问,一片冰心在玉壶. --芙蓉楼送辛渐 持久化数据的第一种方式.在序列化之前也可以把数据打散逐行存储在文件中,然后在逐行读取. 比如定Student类 用字符输出流把Student类的所有属性存入本地文件: 张三|18|男 李四|18|女 读取一行,用|分隔的数据分别为学生的name,age,gender,创建学生对象并加入学生集合 循环上一步直到br.readLine = null 至于这种方法怎么存储对象的其他信息那就不清楚了. 下面来看序列化

【Gson】Gson 使用笔记

Gson 是一款非常好用的 json 处理工具,只需要导一个 gson 的 jar 包就可以使用了,这里简单记录 Gson 的两种常用方法 Json 转 对象 Object object = new Gson().fromJson(json, Object.class); Json 转 Map private Map<String, String> parseJson(String json){ GsonBuilder gsonBuilder = new GsonBuilder(); Gson

Android学习笔记之PopupMenu弹出菜单

(1)布局文件:用于弹出菜单的处罚button: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_paren

GSON学习笔记之初识GSON

引用"JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,採用全然独立于语言的文本格式.为Web应用开发提供了一种理想的数据交换格式. " 曾经手机端与server数据交互的时候用过xml格式,后来又用了JSON格式,无论是server生成json数据,还是手机端解析json数据,尽管用到一些json库,但都比較繁琐.近期从一些项目中发现了Google的gson,就開始学习使用.经过比較,发现gson与其它json库最大的不同是.gson直接使用

Python 学习笔记 - 序列化和反序列化

这一节看看在Python中如何序列化和反序列化.简单的说,序列化就是把内存中保存的数据类型转换为可以存储或者传输的过程,比如说我把一个字典转换为一个字符串这样就可以方便传递或者保存了:反序列化则是倒过来,把字符串转换为对应的数据类型. Python里面常用的有两种方式. JSON Pickle 首先来看看JSON, 例1 比如说我有一个字典如下所示: >>> import json dic={"k1":"v1"} print(dic,type(di