2017-05-05 35 views
3

我有自定義序列化的一個非常特殊的情況下,與GSON:GSON自定義序列與註解

比方說,我有一個下面的類:

public class Student extends BaseModel{ 
    private int id; 
    private String name; 
    private Student goodFriend; 
    private Student bestFriend; 
} 

BaseModel只是我所有的模型類的基類。

當我根本就

gson.toJson(student /* Some Student instance */); 

我將獲得例如:

{ 
id: 1, 
name: "Jack", 
goodFriend: {id: 2, name: "Matt"}, 
bestFriend: {id: 3, name "Tom"} 
} 

這很好,但我需要的是這樣的:

{ 
id: 1, 
name: "Jack", 
goodFriend: 2, // only an ID for this field 
bestFriend: {id: 3, name "Tom"} // whole object for this field 
// both fields are of the same Type, so I can't use TypeAdapterFactory for this 
} 

我需要的一些方法用序列化類型(id或object)標記字段,然後根據需要使用該標記進行序列化。我如何在一般中這樣做,不僅僅是爲了一個學生類,而是爲了BaseModel的所有子類?

我唯一的想法就是使用自定義的註釋: 描述了我想要序列與另一註釋, 對象,我想序列化爲ID只與一個註釋字段,字段,但我做不到找到一種方法來檢索TypeAdapter的寫入方法中的註釋。

任何想法如何處理?

回答

5

我自己找到了答案。事實證明,GSON中已經有這種情況的註釋。它被稱爲@JsonAdapter。

首先,我必須創建一個TypeAdapterFactory:

public class BaseModelForeignKeyTypeAdapterFactory implements TypeAdapterFactory { 

    @Override 
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { 
     if (!BaseModel.class.isAssignableFrom(type.getRawType())) { 
      return null; 
     } 

     TypeAdapter defaultAdapter = gson.getAdapter(type); 

     //noinspection unchecked 
     return (TypeAdapter<T>) new Adapter(defaultAdapter); 
    } 

    private static class Adapter<T extends BaseModel> extends TypeAdapter<T> { 

     private final TypeAdapter<T> defaultAdapter; 

     Adapter(TypeAdapter<T> defaultAdapter) { 
      this.defaultAdapter = defaultAdapter; 
     } 

     @Override 
     public void write(JsonWriter out, T value) throws IOException { 
      out.value(value.getId()); 
     } 

     @Override 
     public T read(JsonReader in) throws IOException { 
      return defaultAdapter.read(in); 
     } 
    } 
} 

創建()方法檢索到默認適配器反序列化領域時GSON將用於該領域,並把它傳遞給使用的適配器。這種方式這個適配器只用於序列化,而反序列化是委託給默認的適配器。

現在我只需要註釋字段我學生類,我想序列化爲標識與此TypeAdapterFactory這樣的:

public class Student extends BaseModel{ 
    private int id; 
    private String name; 

    @JsonAdapter(BaseModelForeignKeyTypeAdapterFactory.class) 
    private Student goodFriend; 

    private Student bestFriend; 
} 

而這一切,現在gson.toJson(student)將輸出:

{ 
id: 1, 
name: "Jack", 
goodFriend: 2, // using "ForeignKey" TypeAdapter 
bestFriend: {id: 3, name "Tom"} // using default TypeAdapter 
} 

我希望這可以幫助別人!

+0

天才! 正是我需要在Android中處理@ColorInt字段。這使我可以讀取十六進制數字或備選顏色名稱,而不是強制使用普通整數。 – mir

+0

很高興我可以幫助:) – jdabrowski