先来看一下Gson官方的阐述
Serializing and Deserializing Generic Types
When you call
toJson(obj), Gson callsobj.getClass()to get information on the fields to serialize. Similarly, you can typically passMyClass.classobject in thefromJson(json, MyClass.class)method. This works fine if the object is a non-generic type. However, if the object is of a generic type, then the Generic type information is lost because of Java Type Erasure. Here is an example illustrating the point:class Foo{ T value; } Gson gson = new Gson(); Foo foo = new Foo (); gson.toJson(foo); // May not serialize foo.value correctly gson.fromJson(json, foo.getClass()); // Fails to deserialize foo.value as Bar
大致意思就是:如果使用 new Gson().fromJson(json, Class
究其原因就一个:Java代码编译后会擦除泛型,从而导致反序列化时,程序不清楚需要反序列化为什么类型的对象实例。
官方也给出了解决方案
The above code fails to interpret value as type Bar because Gson invokes
foo.getClass()to get its class information, but this method returns a raw class,Foo.class. This means that Gson has no way of knowing that this is an object of typeFoo, and not just plainFoo.You can solve this problem by specifying the correct parameterized type for your generic type. You can do this by using the TypeToken class.
Type fooType = new TypeToken>() {}.getType(); gson.toJson(foo, fooType); gson.fromJson(json, fooType); The idiom used to get
fooTypeactually defines an anonymous local inner class containing a methodgetType()that returns the fully parameterized type.
翻译一下大意:可以通过为泛型类型指定正确的参数化类型来解决此问题。您可以通过使用TypeToken类来实现这一点。
借助 TypeToken 这个类对象来弥补这一缺点。
本人所使用的的Gson版本是V2.9.0
官方教程有提到,使用示例:
Type fooType = new TypeToken>() {}.getType();
其中:Foo
gson.fromJson(json, clazz)
而是使用得到的Type类型传入
- gson.fromJson(json, type)
- type -> 为TypeToken后的Type类型
但教程点滞后,因为TypeToken 的构造方法均为protected,且为抽象类。官方提供的了已静态TypeToken.of(clazz) 方法,其内部有一个实现了该类的内部类SimpleTypeToken。
完整的使用示例:
- // 以Foo class为例
- Type type = TypeToken(Foo.class).getType();
- Foo bean = new Gson().from(jsonStr, type);
接下来是针对List
需要借助Gson内部的一些对象来实现。具体代码如下:
- public static
List fromJson(String json, Class entityClazz) { - Gson gson = new Gson();
- // 将数据先转为JsonArray
- JsonArray list = gson.fromJson(json, JsonArray.class);
- // 遍历再将每一个JsonElement反序列化为指定的Type,装进集合后返回
- List
data = new LinkedList<>(); - Type type = TypeToken.of(entityClazz).getType();
- for (JsonElement object : list) {
- data.add(gson.fromJson(object, type));
- }
- return data;
- }
当然还有很多,这只是目前棘手的一点。有兴趣可自行研究,GitHub官网:https://github.com/google/gson/blob/master/UserGuide.md