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

简介: GSON使用笔记(3) -- 如何反序列化出List 时间 2014-06-26 17:57:06  CSDN博客原文  http://blog.csdn.net/zxhoo/article/details/34856061 本文通过3个问题来讨论如何使用 GSON 把JSON反序列化为List。

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类型的对象。

目录
相关文章
|
2月前
|
JSON Java API
GSON 泛型对象反序列化解决方案
GSON 泛型对象反序列化解决方案
|
4天前
|
JSON 数据格式
使用 Gson 将 Map、List等转换为json string
使用 Gson 将 Map、List等转换为json string
11 0
|
2月前
|
JSON Android开发 数据格式
android 使用GSON 序列化对象出现字段被优化问题解决方案
android 使用GSON 序列化对象出现字段被优化问题解决方案
|
9月前
|
Android开发
Android 中使用Gson进行list集合的序列化与反序列化
Android 中使用Gson进行list集合的序列化与反序列化
104 0
|
9月前
|
JSON Java API
Android 中使用Gson完成对象的序列化与反序列化
Android 中使用Gson完成对象的序列化与反序列化
109 0
|
11月前
|
消息中间件 JSON Java
RabbitMQ竟然无法反序列化List
最近在接到了一个需求,大概是通过RabbitMq给xx子系统同步用户数据,要提供单个同步和批量同步。内心暗喜这不简单的很嘛。三下五除二就把代码给写完了但是在联调的过程中,遇到了一个比较奇葩的问题。单个用户进行同步时,子系统可以正常消费。然后进行批量同步的时候,子系统报错了。并抛出java.lang.ClassCastException提示 LinkedHashMap cannot xxxx class 。于是负责子系统的哥们笑嘻嘻的(表面笑嘻嘻)走过来对我说,不是约定List 为啥发个Map过来?看到这个错误,着实让我摸不到头脑。顿时一堆疑问用上心头, 为啥单个对象可以,List就不行
RabbitMQ竟然无法反序列化List
|
11月前
|
存储 Java 索引
|
12月前
|
JSON 数据格式
Json解析问题—数组用Gson反序列化为List双引号消失
现在的目的是这样的,我想从一串Object类型的字符串,转化成对应的实体类对象。 简单来说就是把这个字符串给一个个独立分开。 我先写出实体类对象和Json的数据,看完再开始解析。
106 0
|
2月前
|
存储 XML JSON
数据传输的艺术:深入探讨序列化与反序列化
数据传输的艺术:深入探讨序列化与反序列化
60 0
|
1月前
|
JSON 安全 Java
Spring Boot 序列化、反序列化
本文介绍了Spring Boot中的序列化和反序列化。Java提供默认序列化机制,通过实现Serializable接口实现对象到字节流的转换。Spring Boot默认使用Jackson处理JSON,可通过注解和配置自定义规则。然而,序列化可能引发安全问题,建议使用白名单、数据校验和安全库。最佳实践包括使用标准机制、自定义规则及注意版本控制。文章还提醒关注性能并提供了相关参考资料。
47 2