Kotlin之應用Gson

引言


Gson是不是很簡潔很容易上手呢?最主要的就兩個方法toJson()和fromJson()將實體轉爲Json和將Json轉爲實體。

我之前沒有使用過Gson,更不用說是用Kotlin了。由於使用的時間還不是很長,好不好用還真不好說。

我之前用慣了Json且有這個JsonHelper工具類的幫助,暫時性的認爲沒有JsonHelper好用且功能不如JsonHelper的實用。

主要是因爲碰到了下文將要講述的坑。

正文


我在編寫項目的過程中,需要將一些暫時性的數據進行保存,自然而然的就想到了之前創建的SpUtils類將數據存儲在SharedPreferences中。

於是寫了兩個方法,完美實現需求

        fun <T> getObject(key: String, cls: Class<T>): T {
            var value = getString(key, "")
            return gson.fromJson<T>(value, cls)
        }

        fun setObject(key: String, obj: Any) {
            var value = gson.toJson(obj)
            setString(key, value)
        }

思路主要是將實體轉換成Json字符串保存,需要時取出Json字符串並序列化成實體返回。

這時需求升級了,需要保存一個列表。

        fun <T> getList(key: String, cls: Class<T>): List<T> {
            var value = getString(key, "")
            if (TextUtils.isEmpty(value)) {
                return ArrayList()
            }
            return gson.fromJson(value, object : TypeToken<List<T>>() {}.type)
        }

這時看着沒毛病吧,程序也能夠正常的編譯,但運行到取實體的變量時卻崩潰了

error

類型轉換失敗??爲什麼呢??debug走一遍

存儲的數據

存儲的Json

取出的數據

問題出現了,原本List裏面包含的對象,經過一遍存儲和取出,List裏卻變成了鍵值對。

可以得出結論Gson並沒有序列化成功。

費了不少心思,搜尋了很多資料,終於明白了。原因是java的類型擦除

Java中的泛型基本上都是在編譯器這個層次來實現的。在生成的Java字節碼中是不包含泛型中的類型信息的。使用泛型的時候加上的類型參數,會在編譯器在編譯的時候去掉。這個過程就稱爲類型擦除。
https://segmentfault.com/q/1010000009644038

由於我是用了泛型,導致fromJson()只知道是List而裏面的類型卻是未知的,因此返回成了鍵值對。

所以這裏採用傳遞type的方式,否則會因爲找不到類型,而序列化失敗

        fun <T> getList(key: String, type: Type): T {
            var value = getString(key, "")
            return gson.fromJson(value, type)
        }
SpUtils.getList<List<Category>>(KEY_CATEGORY_LIST, object : TypeToken<List<Category>>() {}.type)

從這一點看之前的JsonHelper就不會有這種問題。

不能一棍子打死,我還是抱着學習的態度繼續深入。

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