【Android 入門開發實戰:口罩地圖】Gson 資料解析方式

【Android 入門開發實戰:口罩地圖】線上免費講義課程目錄

JSON 資料在解析時,較為耗手機效能、處理也較慢,所以在解析資料時,業界普遍會透過 Gson 來解析 JSON 資料格式。Gson 是 Google 開發的開源 Library。這一節課程,我們將來介紹,如何使用 Gson 來解析資料。

添加 Gson 依賴庫 (dependencies)

在 GRADLE (Module) 層級 dependencies 內加入:

implementation 'com.google.code.gson:gson:2.8.6'

資料轉換

JSON 資料轉換成 Gson 是透過 Gson 提供的 fromJson(String json, Class<T> classOfT) 這個方法。其中,fromJson 第一個欄位,要帶入的即是我們透過 Okhttp 獲取到的資料,第二個欄位,需帶入我們自己定義的類別。

//pharmaciesData 為 Okhttp 獲取到的資料
val pharmaciesData = response.body?.string()

//PharmacyInfo 是我們自定義類別
val pharmacyInfo = Gson().fromJson(pharmaciesData, PharmacyInfo::class.java)

PharmacyInfo

JSON 資料轉換成 Gson,仍須注意的是資料層次概念以 口罩資料 為例,若我們要取得最外層資料,如:「 “type”: “FeatureCollection”」,我們可以寫成這樣:

class PharmacyInfo(
    @SerializedName("type")
    val type: String
)

SerializedName 裡面要填的是,真實資料中的名稱,我們要獲取 type 所以填 type,所以寫成「@SerializedName(“type”)」以此類推。而如果你不喜歡,原本資料定義的名稱,你可以自定義常數值名稱,例如,想改成 my_type,就可以寫成這樣:

class PharmacyInfo(
    @SerializedName("type")
    val my_type: String
)

而如果我們想要印出資料,可以寫成這樣:

Log.d("HKT", "my_type: ${pharmacyInfo.my_type}")

輸出結果

my_type: FeatureCollection

而在原本 JSON 資料解析裡,如果我們沒有多加 has 或 isNull 來判斷欄位資料是否存在,會直接噴出例外錯誤。但是如果是 GSON,並不用多加判斷,只是因為沒有此筆欄位資料會回傳 null。例如,我們資料並沒有 typeeeeee 但我們寫成這樣:

class PharmacyInfo(
    @SerializedName("typeeeeee")
    val my_type: String
)

輸出結果

my_type: null

陣列與物件屬性的資料轉換

如果我們要獲取每間藥局名稱,剛開始學的的同學最容易犯的錯誤,會寫成這樣:

//錯誤範例
class PharmacyInfo(
    @SerializedName("name")
    val name: String
)

這樣的結果,GSON 並不會噴出例外錯誤,只是會得到 null 。這個問題出在資料層次問題,必須清楚的跟電腦說你要獲取哪一層資料,上方的寫法,電腦會誤以為你要獲取取第一層,但實際你是要獲取 features 「陣列」裡面的 properties 「物件」裡面的 name 值。所以應該改成:

class PharmacyInfo(
    @SerializedName("features")
    val features: List<Feature>
)

class Feature(
    @SerializedName("properties")
    val property: Property
)

class Property(
    @SerializedName("name")
    val name: String
)

層次中最需要注意的是,大括號 object {} 與中括號 array [],層次概念。瞭解之後,我們就可以透過 for 迴圈,取出每一間藥局名稱。

val pharmaciesData = response.body?.string()
val pharmacyInfo = Gson().fromJson(pharmaciesData, PharmacyInfo::class.java)

for (i in pharmacyInfo.features) {
    Log.d("HKT", "name: ${i.property.name}")
}

輸出結果

name: 中美藥局
name: 新東洋藥局
name: 辰好藥局
name: 杏安藥局
name: 明皇藥局
name: 全國大藥局
name: 政德藥局
name: 嘉方藥局
name: 慶豐綜合藥局
...
...
...

KT 的偷呷步

安裝外掛套件:「JSON To Kotlin Class」,快速將 JSON 資料轉換成 Class。

完整口罩資料類別定義

透過外掛套件的方式,快速幫我們產生對應的資料類別結構,並將原本分散的檔案,刻意全部集中到「PharmacyInfo.kt」檔案中,若採用外掛套件產生個別分開檔案也可,看公司文化或個人喜好。

package com.thishkt.pharmacydemo.data

data class PharmacyInfo(
    val features: List<Feature>,
    val type: String
)

data class Feature(
    val geometry: Geometry,
    val properties: Properties,
    val type: String
)

data class Geometry(
    val coordinates: List<Double>,
    val type: String
)

data class Properties(
    val address: String,
    val available: String,
    val county: String,
    val cunli: String,
    val custom_note: String,
    val id: String,
    val mask_adult: Int,
    val mask_child: Int,
    val name: String,
    val note: String,
    val phone: String,
    val service_periods: String,
    val town: String,
    val updated: String,
    val website: String
)

參考資料

Gson User Guide
https://github.com/google/gson

程式碼範例

範例名稱:Gson_資料解析_印出藥局名稱
開發人員:HKT (侯光燦)
程式語言:Kotlin
開發環境:Android Studio 4.1.1 & Android 11 & Kotlin 1.4.21
授權範圍:使用時必須註明出處且不得為商業目的之使用
範例下載點:點我下載

這個網誌中的熱門文章

2023 最新入門零基礎 Kotlin教學【從零開始學 Kotlin 程式設計】Kotlin 教學課程目錄 (Android Kotlin, IntelliJ IDEA, Android Studio, Android APP 開發教學)

2022 最新入門零基礎 Flutter教學 【Flutter 程式設計入門實戰 30 天】Flutter 教學課程目錄 (IntelliJ IDEA 開發教學)

nano 文字編輯器

16天記下7000單字

startActivityForResult is deprecated 已廢棄替代解決方式