java 泛型序列化_Java中泛型集合List<T>反序列化问题及解决方法
发布日期:2021-06-24 13:33:31 浏览次数:2 分类:技术文章

本文共 2232 字,大约阅读时间需要 7 分钟。

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

问题1

有这样两个类:

class MyObj {

int x;

}

class MyList {

List 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 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 list = new Gson().fromJson("[{x:1}]", ArrayList.class);

更糟糕,连编译都无法通过!因为Java的泛型是用 擦拭法

实现的,说白了只是编译器提供给程序员的语法糖,根本不存在ArrayList这样一个类。那么怎样才能让GSON反序列化出我们想要的泛型对象呢?答案是,请TypeToken帮忙:

@Test

public void test3() {

Type type = new TypeToken>() {}.getType();

ArrayList list = new Gson().fromJson("[{x:1}]", type);

Assert.assertEquals(1, list.size());

Assert.assertEquals(MyObj.class, list.get(0).getClass());

}

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

问题3

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

public static ArrayList jsonToList(String json, Class classOfT) {

Type type = new TypeToken>() {}.getType();

return new Gson().fromJson(json, type);

}

这个测试能通过吗?

@Test

public void test4() {

ArrayList 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 ArrayList jsonToList(String json, Class classOfT) {

Type type = new TypeToken>(){}.getType();

ArrayList jsonObjs = new Gson().fromJson(json, type);

ArrayList listOfT = new ArrayList<>();

for (JsonObject jsonObj : jsonObjs) {

listOfT.add(new Gson().fromJson(jsonObj, classOfT));

}

return listOfT;

}

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

转载地址:https://blog.csdn.net/weixin_33212263/article/details/114067456 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:java类加载路径_Java中获取类加载路径和项目根路径
下一篇:网易python面试_一道神奇的Python面试题,你会吗?

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月02日 01时52分50秒