1. 程式人生 > >[Android] Gson高階用法:Json串轉換成介面欄位

[Android] Gson高階用法:Json串轉換成介面欄位

工作後就很少更新部落格,這兩天在Json解析的時候遇到問題,空了正好記錄下。

問題
將後端獲取資料轉換成客戶端建立的模型,然後轉換成Json串存入資料庫。當在無網路的情況下,則會從資料庫從取出資料轉換成客戶端建立的模型。這些模型中有所有非基本資料型別欄位都是用介面表示,在這將物件轉成json的時候沒有問題,但是反過來將json轉成物件的時候卻發現失敗了,示例程式碼如下:

        Gson gson = new Gson();
        gson.fromJson(jsonData, Model.class);

這是因為在轉換成物件的時候,Gson並不知道該介面對應的實現類是什麼,導致轉換失敗。
解決方案


在查閱資料後得知Gson提供了一個叫“TypeAdapter”的東西,它可以攔截解析的過程,使用者可以指定jsonObject所對應的型別。具體Gson實現原理可以參考這篇文章 ,借用文章中的一張圖
Gson解析原理

從圖中可以知道,我們在建立gson物件的時候可以利用GsonBuilder注入一個自定義的TypeAdapter物件攔截解析過程從而處理目標物件中一些特殊的欄位。
實戰
下面我舉一個例子具體說明,下圖是資料模型UML
這裡寫圖片描述

  • Json串的生成
        Course course = new Course();
        course.addUnit(new
Video()); String jsonData = new GsonBuilder().create().toJson(course);
  • Json串轉換成物件[重點]
        Gson newGson = new GsonBuilder().registerTypeAdapter(Unit.class, new JsonDeserializer<Unit>() {
            @Override
            public Unit deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws
JsonParseException { return jsonDeserializationContext.deserialize(jsonElement, Video.class); } }).registerTypeAdapter(Info.class, new JsonDeserializer<Info>() { @Override public Info deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { return jsonDeserializationContext.deserialize(jsonElement, InfoImpl.class); } }) .create(); Course course = newGson.fromJson(jsonData, Course.class);