使用Gson的一些感悟——解析復(fù)雜json
將json解析為泛型對象時,發(fā)現(xiàn)Gson有種很特別的寫法,因此學(xué)習(xí)了下。
需要將如下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();
定義一個繼承于泛型參數(shù)類型為Collection<Integer> 的Typetoken類的子類(語文不好,我重新說,定義一個匿名類,它的父類是泛型參數(shù)類型為
Collection<Integer>的TypeToken泛型類)。
之所以要這么寫,是因為java的泛型類型擦除導(dǎo)致的(網(wǎng)上資料很多),直接看下面例子。
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());
}
}
運(yùn)行結(jié)果:
java.lang.Object
com.yu.testGenericClass$F<java.lang.String>
顯而易見,泛型類F的對象obj的泛型參數(shù)類型String已經(jīng)被擦除,現(xiàn)在就知道是Object了。而繼承自泛型參數(shù)為String的F的匿名類的對象subclassType的直接父類信息上還保留著泛型參數(shù)的信息。
其實還有一種寫法就是將泛型參數(shù)作為實參傳遞,無奈Gson的Typetoken這個類的構(gòu)造函數(shù)是protected(不過仔細(xì)想想,還是Gson的處理方式更優(yōu)雅,就是丑了點...)
回到開始的問題,要解析開頭這段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的內(nèi)部處理也是讓人眼界大開,對反射的用法可謂精深,等有時間再好好總結(jié)下。