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

时间 2014-06-26 17:57:06  CSDN博客原文  http://blog.csdn.net/zxhoo/article/details/34856061

本文通过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的更多相关文章

  1. Gson 简易笔记

    #Gson 简易笔记 之前用 fastjson.它连个规矩的文档都没有,而且在github的wiki上写着: gson的g可能是"龟"拼音的缩写,龟速的json库." 各 ...

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

    http://blog.csdn.net/zxhoo/article/details/21471005 GSON是Google发布的JSON序列化/反序列化工具,非常容易使用.本文简要讨论在使用GSO ...

  3. Android Gson使用笔记

    最近在做一个java web service项目,需要用到jason,本人对java不是特别精通,于是开始搜索一些java平台的json类库. 发现了google的gson,因为之前对于protoco ...

  4. Json工具类库之Gson实战笔记

    日常接口的数据传输通常使用xml或者json来传递数据,xml较庞大但是描述数据能力十分出众,json数据结构较小而且支持ajax传输,xml在数据传输和解析资源占用都比较逊色于json.因此日常的接 ...

  5. Gson、jackson 序列化,反序列化(单个、集合)

    实体类: package com.nf.redisDemo1.entity; public class News { private long id; private String title; pr ...

  6. Java Gson 简要笔记

    Gson是Google开发的Java比较好用的 Json工具. 使用挺简单,假设有个类: class Runner { int attr; String name; public Runner(int ...

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

    序列化其实就是将一个对象的所有相关的数据保存为一个二进制文件(注意:是一个对象) 而且与这个对象相关的所有类型都必须是可序列化的所以要在相关类中加上 [Serializable]特性 对象类型包括:对 ...

  8. Android笔记——Drawerlayout创建侧滑出菜单

    1.首先务必导入support-v4包 2.布局文件主标签为<android.support.v4.widget.DrawerLayout>,并为其设置id         其子标签必须包 ...

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

    寒雨连江夜入吴,平明送客楚山孤. 洛阳亲友如相问,一片冰心在玉壶. --芙蓉楼送辛渐 持久化数据的第一种方式.在序列化之前也可以把数据打散逐行存储在文件中,然后在逐行读取. 比如定Student类 用 ...

随机推荐

  1. 一个支持国密SM2/SM3/SM4/SM9/ZUC/SSL的密码工具箱

    转:https://blog.csdn.net/xuq09/article/details/91815366 The GmSSL Project网址:http://gmssl.org/docs/qui ...

  2. 吴裕雄 PYTHON 神经网络——TENSORFLOW 学习率的设置

    import tensorflow as tf TRAINING_STEPS = 10 LEARNING_RATE = 1 x = tf.Variable(tf.constant(5, dtype=t ...

  3. FTP-Publisher Plugin

    使用 FTP-Publisher Plugin 在 http://wiki.hudson-ci.org/display/HUDSON/FTP-Publisher+Plugin 有详细说明, 需要注意的 ...

  4. 前端学习 之 JavaScript基础

    一. JavaScript简介 1. JavaScript的历史背景介绍 1994年,网景公司(Netscape)发布了Navigator浏览器0.9版.这是历史上第一个比较成熟的网络浏览器,轰动一时 ...

  5. 数字反转(0)<P2011_1>

    数字反转  (reverse.cpp/c/pas) [问题描述] 给定一个整数,请将该数各个位上数字反转得到一个新数.新数也应满足整数的常见形 式,即除非给定的原数为零,否则反转后得到的新数的最高位数 ...

  6. Keras下载的数据集以及预训练模型保存在哪里

    Keras下载的数据集在以下目录中: root\\.keras\datasets Keras下载的预训练模型在以下目录中: root\\.keras\models 在win10系统来说,用户主目录是: ...

  7. [read -p应用]插拔光模块去检查port present状态

    #!/bin/bash path="/sys/devices/platform/soc/fd880000.i2c-pld/i2c-0/i2c-4/i2c-15/15-0060" a ...

  8. WPS Linux 2019领先的背后

    导读 过去很多年,作为民族办公领导品牌,金山办公持续高度重视对基础办公软件发展的布局和投入,这其中包括大量的研发资金.人力投入,真正做到了超过30年不忘初心,坚守办公阵地. 早在2019年3月26日, ...

  9. springboot下使用dubbo的简单demo

    1.一些话 现在java后端开发大多用springboot来简化环境搭建,现在一直使用的是springcloud和k8s有关的东西,以前用过dubbo,但那会儿的开发环境搭建流程较为繁琐,而且不支持r ...

  10. GsonUtils.getGson().fromJson() 转泛型集合用法

    //计算其他收费 List<QiTaFree> qiTaFreeList = GsonUtils.getGson().fromJson(exhiMain.getQiTaFressJson( ...