本篇文章同步發表在 HKT 線上教室 部落格,線上影音教學課程已上架至 Udemy 和 Youtube 頻道。另外,想追蹤更多相關技術資訊,歡迎到 臉書粉絲專頁 按讚追蹤喔~
範例名稱:Gson 資料解析並印出藥局名稱
開發人員:HKT (侯光燦)
程式語言:Kotlin
開發環境:Android Studio 4.1.1 & Android 11 & Kotlin 1.4.21
授權範圍:使用時必須註明出處且不得為商業目的之使用
範例下載點:點我下載
JSON 資料在解析時,較為耗手機效能、處理也較慢,所以在解析資料時,業界普遍會透過 Gson 來解析 JSON 資料格式。Gson 是 Google 開發的開源 Library。這一節課程,我們將來介紹,如何使用 Gson 來解析資料。
在 GRADLE (Module) 層級 dependencies 內加入:
implementation 'com.google.code.gson:gson:2.8.6'
JSON 資料轉換成 Gson 是透過 Gson 提供的 fromJson(String json, Class classOfT) 這個方法。其中,fromJson 第一個欄位,要帶入的即是我們透過 Okhttp 獲取到的資料,第二個欄位,需帶入我們自己定義的類別。
//pharmaciesData 為 Okhttp 獲取到的資料
val pharmaciesData = response.body?.string()
//PharmacyInfo 是我們自定義類別
val pharmacyInfo = Gson().fromJson(pharmaciesData, PharmacyInfo::class.java)
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: 慶豐綜合藥局
...
...
...
安裝外掛套件:「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
)
HKT 線上教室
https://tw-hkt.blogspot.com/
Freepik
https://www.freepik.com/
Gson User Guide
https://github.com/google/gson
那今天【iThome 鐵人賽】就介紹到這邊囉~
順帶一提,KT 線上教室,臉書粉絲團,會不定期發佈相關資訊,不想錯過最新資訊,不要忘記來按讚,追蹤喔!也歡迎大家將這篇文章分享給更多人喔。
我們明天再見囉!!!掰掰~