Gson gson = new Gson(); // Or use new GsonBuilder().create();
MyType target = new MyType();
String json = gson.toJson(target); // serializes target to Json
MyType target2 = gson.fromJson(json, MyType.class); // deserializes json into target2
Type listType = new TypeToken<List<String>>() {}.getType();
List<String> target = new LinkedList<String>();
target.add("blah");
Gson gson = new Gson();
String json = gson.toJson(target, listType);
List<String> target2 = gson.fromJson(json, listType);
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {對於複雜的集合類型中使用了泛型來限制如 List<Object>,在Gson裏面通過TypeToken類,更爲通用的方法來有效的解決泛型的問題。
Object object = fromJson(json, (Type) classOfT);
return Primitives.wrap(classOfT).cast(object);
}
public class TypeToken<T> {
final Class<? super T> rawType;
final Type type;
final int hashCode;
@SuppressWarnings("unchecked")注意:TypeToken<T>類的構造方法是Protected的,使用者必須通過繼承的方式,或者匿名類的方式來生成一個TypeToken對象。比如:
protected TypeToken() {
this.type = getSuperclassTypeParameter(getClass());
this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);
this.hashCode = type.hashCode();
}
TypeToken<List<String>> list = new TypeToken<List<String>>() {};//注意:T不能使用帶有通配符的參數如
Class<?>,或
List<? extends CharSequence>
static Type getSuperclassTypeParameter(Class<?> subclass) {
Type superclass = subclass.getGenericSuperclass();
if (superclass instanceof Class) {
throw new RuntimeException("Missing type parameter.");
}
ParameterizedType parameterized = (ParameterizedType) superclass;
return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
}
3.1 多個類的嵌套的例子
GSON
可以很容易地序列化和反序列化靜態嵌套類。
但是GSON
不能自動反序列化的純內部類,因爲它們的無參構造函數需要引用的對象在反序列化時是無法使用的.
你可以通過使用靜態內部類或給它提供一個定製的InstanceCreator
來解決這個問題。下面是一個例子:
//NOTE: 這個class B 在默認情況下不會被`GSON`序列化
public class A {
public String a;
class B {
public String b;
publicB() {// No args constructor for B
}
}
}
}
GSON
不能反序列化{"b":"abc"}
,因爲class
B
是一個內部類,如果你這麼定義B: static
class B
, GSON
是能反序列化這段字符串的,
另外一個辦法就是自定義個實例構建方法,下面是一個例子
//NOTE: 這樣可行,但是不推薦
public class InstanceCreatorForB implements InstanceCreator<A.B> {
privatefinal A a;
public InstanceCreatorForB(A a){
this.a= a;
}
public A.BcreateInstance(Type type){
return a.newB();
}
}
3.2 集合的例子
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);//ints,ints2是一樣的
集合限制
- 能夠序列化任何任意類型的集合,但是不能讓它反序列化,因爲使用者沒有辦法給指示數據類型
- 反序列化的時候,集合一定得是一個特定泛型的集合
3.3 泛型的序列化和反序列化
當你調用toJson(obj)
的時候,GSON
會執行obj.getClass()
來獲取序列化的字段的信息,同樣的,你可以在fromJson(json,
MyClass.class)
方法中使用典型對象.如果對象是一個非泛型對象,這樣也能正常工作.但是, 如果對象是一個泛型對象,Java
的類型擦除會讓這個對象丟失泛型類型信息.
可以通過使用TypeToken類指定正確的參數化類型的泛型類型來解決這個問題。原理就是上面2.2 Gson解析部分。
3.4 任意對象集合的序列化和反序列化
有時你會處理一些混合類型的JSON
,比如
['hello',5,{name:'GREETINGS',source:'guest'}]
static class Event{
private String name;
private String source;
privateEvent(String name, String source){
this.name= name;
this.source= source;
}
@Override
public String toString(){
return String.format("(name=%s, source=%s)", name, source);
}
}
public static void main(String[] args){
Gson gson =new Gson();
Collection collection =new ArrayList();
collection.add("hello");
collection.add(5);
collection.add(new Event("GREETINGS","guest"));
String json = gson.toJson(collection);
System.out.println("Using Gson.toJson() on a raw collection: "+ json);
JsonParser parser =new JsonParser();
JsonArray array = parser.parse(json).getAsJsonArray();
String message = gson.fromJson(array.get(0), String.class);
int number = gson.fromJson(array.get(1),int.class);
Event event = gson.fromJson(array.get(2), Event.class);
System.out.printf("Using Gson.fromJson() to get: %s, %d, %s", message, number, event.toString());
}
使用GSON
序列化這個集合只需要調用toJson(collection)
,而且不用設置其他任何東西.但是你要是通過fromJson(json,
Collection.class)
反序列化這個集合的話是不可行的,因爲GSON
,沒辦法匹配集合類型,所以GSON
需要你提供這個集合序列化的類型.有三個選則:
- 使用
GSON
的解析器API
(底層流解析器或DOM解析器JsonParser
)來解析數據元素,然後在每一個元素上使用Gson.fromJson()
.這是首選的方法。 - 給
Collection.class
註冊類型適配器,讓每一個元素都對應自己的對象.缺點是會搞亂
GSON`中其他的集合的反序列化. - 通過註冊一個
MyCollectionMemberType
使用fromJson
和Collection<MyCollectionMemberType>
,缺點就是隻有數組是頂級元素纔是可行的
3.5 從序列化和反序列化中剔除字段
GSON支持剔除頂層類,字段和字段類型,下面是一種排除字段或者類的可插拔的機制,如果這些機制沒有滿足你的需要.你可以自定義序列化和反序列化的解釋器.
默認的情況下,如果一個對象被聲明爲transient
,static
,那麼它就會被剔除.
如果你要包含這些字段,可以用如下代碼:Gson gson = new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.STATIC)
.create();
Gson gson = new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)
.create();
自定義的剔除策略
如果這些默認的策略都不能滿足你的需求,你還可以自定自己的策略,更多可見ExclusionStrategy
下面是一個使用@Foo
的例子
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Foo {
// Field tag only annotation
}
public class SampleObjectForTest {
@Foo private final int annotatedField;
private final String stringField;
private final long longField;
private final Class<?> clazzField;
public SampleObjectForTest() {
annotatedField = 5;
stringField = "someDefaultValue";
longField = 1234;
}
}
public class MyExclusionStrategy implements ExclusionStrategy {
private final Class<?> typeToSkip;
private MyExclusionStrategy(Class<?> typeToSkip) {
this.typeToSkip = typeToSkip;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return (clazz == typeToSkip);
}
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getAnnotation(Foo.class) != null;
}
}
public static void main(String[] args) {
Gson gson = new GsonBuilder()
.setExclusionStrategies(new MyExclusionStrategy(String.class))
.serializeNulls()
.create();
SampleObjectForTest src = new SampleObjectForTest();
String json = gson.toJson(src);
System.out.println(json);
}
======== OUTPUT ========
{"longField":1234}
3.6 自定義序列化和反序列化
有時默認的內置序列化或反序列化的描述,並不是你想要的,比如做時間之類的處理的時候這種問題經常出現,Gson
允許你自定義序列化工具:
- Json Serialiers: 需要定義自定義序列化對象
- Json Deserializers: 需要定義自定義反序列化的類型
- Instance Creators: 無參構造方法和反序列化解析器都不是必須的
- 緊湊漂亮的JSON輸出
- NULL對象的支持
- 版本支持
- 字段命名支持