使用Gson的一些感悟——解析复杂json
将json解析为泛型对象时,发现Gson有种很特别的写法,因此学习了下。
需要将如下json解析为对象
{
"acs-engine-autoscaler": [
{
"apiVersion": "v1",
"version": "2.1.4"
}
],
"aerospike": [
{
"appVersion": "v3.14.1.2",
"version": "0.1.7"
}
],
"anchore-engine": [
{
"appVersion": "0.2.4",
"version": "0.2.6"
}
]
}
阅读Gson的官方指引,有如下用法:
Collection Type
Gson gson = new Gson();
Collection<Integer> ints = Lists.immutableList(1,2,3,4,5);
// Serialization
String json = gson.toJson(ints); // ==> json is [1,2,3,4,5]
// Deserialization
Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
Collection<Integer> ints2 = gson.fromJson(json, collectionType);
重点在这句:
Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
定义一个继承于泛型参数类型为Collection<Integer>
的Typetoken
类的子类(语文不好,我重新说,定义一个匿名类,它的父类是泛型参数类型为
Collection<Integer>
的TypeToken
泛型类)。
之所以要这么写,是因为java的泛型类型擦除导致的(网上资料很多),直接看下面例子。
package com.yu;
import java.lang.reflect.Type;
public class testGenericClass {
private static class F<T>{
public T name;
}
public static void main(String args[]) {
F<String> obj = new F<String>();
Type subclassType = new F<String>(){}.getClass().getGenericSuperclass();
Type type = obj.getClass().getGenericSuperclass();
System.out.println(type.getTypeName());
System.out.println(subclassType.getTypeName());
}
}
运行结果:
java.lang.Object
com.yu.testGenericClass$F<java.lang.String>
显而易见,泛型类F
的对象obj
的泛型参数类型String
已经被擦除,现在就知道是Object
了。而继承自泛型参数为String
的F
的匿名类的对象subclassType
的直接父类信息上还保留着泛型参数的信息。
其实还有一种写法就是将泛型参数作为实参传递,无奈Gson的Typetoken这个类的构造函数是protected
(不过仔细想想,还是Gson的处理方式更优雅,就是丑了点...)
回到开始的问题,要解析开头这段json就两句即可。
Type t = new TypeToken<Map<String, VersionDO[]>>() {}.getType();
Map<String, VersionDO[]> result = new Gson().fromJson(jsonContent, t);
class VersionDO {
private String apiVersion;
private String version;
}
Gson的内部处理也是让人眼界大开,对反射的用法可谓精深,等有时间再好好总结下。
网友评论