每天記錄學習的新知識 :Gson自定義類型適配器TypeAdapter

參考地址

參考和轉載地址:你真的會用Gson嗎?Gson使用指南(四)
參考地址:Gson全解析(中)-TypeAdapter的使用

TypeAdapter

TypeAdapter 是Gson自2.0(源碼註釋上說的是2.1)開始版本提供的一個抽象類,用於接管某種類型的序列化和反序列化過程,包含兩個注要方法 write(JsonWriter,T) 和 read(JsonReader) 其它的方法都是final方法並最終調用這兩個抽象方法。

API

public abstract class TypeAdapter<T> {

	//序列化
	public abstract void write(JsonWriter out, T value) throws IOException;

	//方法名稱指明瞭需要做的業務,參數則提供了更通用的入參類型Writer。
	//該方法可以把對象輸出到Writer類型的輸出流中。內部實現上使用包裝類JsonWtiter完成輸出格式的轉換
	public final void toJson(Writer out, T value) throws IOException {...}

	public final TypeAdapter<T> nullSafe() {...}
	
	//方法不指定輸出參數,默認返回json格式的String類型結果。
	//實際上使用的是StringWriter完成輸出流轉換的,具體操作是,創建StringWriter之後,調用前面的方法。
	//從而完成json數據格式轉換
    public final String toJson(T value) {...}

	//解析json數據,從JsonReader中讀取json數據,並完成對象創建和屬性賦值,從而恢復出完成的數據對象
    public final JsonElement toJsonTree(T value) {...}

	//反序列化
	public abstract T read(JsonReader in) throws IOException;

	//對read方法的擴展,接受更加通用的Reader格式輸入,內部實現使用JsonReader對Reader包裝,
	//完成輸入流格式轉換,並調用前一個方法,達到從輸入流恢復出對象的目的
    public final T fromJson(Reader in) throws IOException {...}

	//從json字符串恢復對象屬性,使用StringReader對String類型的輸入數據進行包裝,並且調用前面的方法,達成對象賦值的目的
    public final T fromJson(String json) throws IOException {...}

	//從JsonElement中恢復對象信息,使用JsonTreeReader對JsonElement類型的輸入數據進行包裝,然後調用前面的方法恢復出數據對象
    public final T fromJsonTree(JsonElement jsonTree) {...}

}

例子

轉載自:Gson全解析(中)-TypeAdapter的使用

public class Book {

    private String[] authors;
    private String isbn;
    private String title;
	...
}
public class BookTypeAdapter extends TypeAdapter<Book> {

    @Override
    public void write(JsonWriter out, Book value) throws IOException {
        out.beginObject();
        out.name("isbn").value(value.getIsbn());
        out.name("title").value(value.getTitle());
        out.name("authors").value(value.getAuthors()[0] + ";yoshin");
        out.endObject();
    }

    @Override
    public Book read(final JsonReader in) throws IOException {
        final Book book = new Book();

        in.beginObject();
        while (in.hasNext()) {
            switch (in.nextName()) {
                case "isbn":
                    book.setIsbn(in.nextString());
                    break;
                case "title":
                    book.setTitle(in.nextString());
                    break;
                case "authors":
                    book.setAuthors(in.nextString().split(";"));
                    break;
            }
        }
        in.endObject();

        return book;
    }

}

調用

    public void main() {
        final GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.registerTypeAdapter(Book.class, new BookTypeAdapter());
        gsonBuilder.setPrettyPrinting();

        final Gson gson = gsonBuilder.create();

        final Book book = new Book();
        book.setAuthors(new String[]{"Joshua Bloch", "Neal Gafter"});
        book.setTitle("Java Puzzlers: Traps, Pitfalls, and Corner Cases");
        book.setIsbn("978-0321336781");

        final String json = gson.toJson(book);
        System.out.println("Serialised");
        System.out.println(json);

        final Book parsedBook = gson.fromJson(json, Book.class);
        System.out.println("\nDeserialised");
        System.out.println(parsedBook);
    }

輸出:

I/System.out: Serialised
I/System.out: {
I/System.out:   "isbn": "978-0321336781",
I/System.out:   "title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases",
I/System.out:   "authors": "Joshua Bloch;yoshin"
I/System.out: }
I/System.out: Deserialised
I/System.out: Book{authors=[Joshua Bloch, yoshin], isbn='978-0321336781', 
						title='Java Puzzlers: Traps, Pitfalls, and Corner Cases'}

分析:

Serialised 是序列化後的結果;Deserialised是反序列後的結果。

TypeAdapter內包含序列化和反序列化兩個自定義步驟。
其中write是序列化後的過程;read是反序列化的過程。

2.1 序列化

    @Override
    public void write(JsonWriter out, Book value) throws IOException {
        out.beginObject();
        out.name("isbn").value(value.getIsbn());
        out.name("title").value(value.getTitle());
        out.name("authors").value(value.getAuthors()[0] + ";yoshin");
        out.endObject();
    }

以上是序列化的自定義過程。

其中,如果想輸出Object類型,則:out.beginObject();和 out.endObject();成對出現;
如果需要輸出Array,則: out.beginArray();和 out.endArray();成對出現。

最終Book會輸出成JsonWriter。

2.2 反序列化

    @Override
    public Book read(final JsonReader in) throws IOException {
        final Book book = new Book();

        in.beginObject();
        while (in.hasNext()) {
            switch (in.nextName()) {
                case "isbn":
                    book.setIsbn(in.nextString());
                    break;
                case "title":
                    book.setTitle(in.nextString());
                    break;
                case "authors":
                    book.setAuthors(in.nextString().split(";"));
                    break;
            }
        }
        in.endObject();

        return book;
    }

以上是自定義反序列化的過程。

接收Object類型需要:in.beginObject();和 in.endObject();
接收Array類型需要: in.beginArray();和 in.endArray();

這是一個由JsonReader 轉化成Book數據的過程。

JsonReader 提供的方法:
有沒有數據:in.hasNext()
下一個KEY名:in.nextName()

總結

TypeAdapter是泛型設計,提供了基本的接口(序列化和反序列化)封裝,但是核心的reader和writer接口還需要子類實現。

如果想把序列化和反序列化分開,只做其一操作,可以實現JsonSerializer 和JsonDeserializer。 不用像TypeAdapter一樣,必須要實現序列化和反序列化的過程,你可以據需要選擇,如只接管序列化的過程就用 JsonSerializer ,只接管反序列化的過程就用 JsonDeserializer。

工作原理(轉載自)

1)通過GsonBuilder註冊TypeAdapter,並把TypeAdapter封裝成TypeAdpterFactory對象
2)將封裝成的TypeAdapterFactory通過GsonBuilder的create傳入Gson對象中並返回
3)調用gson.fromJson方法,調用getTypeAdapter方法返回你自定義的Adapter,並調用其reader方法進行處理!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章