本篇文章同步发表在 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 线上教室,脸书粉丝团,会不定期发布相关资讯,不想错过最新资讯,不要忘记来按赞,追踪喔!也欢迎大家将这篇文章分享给更多人喔。
我们明天再见罗!!!掰掰~
<<: D-20. 预设更改DBMS 、bundle指令 、Gemfile && Reverse String II && III
这篇是在讲React的测试,所以就拿个几天篇幅来讲hooks,React在v16.8之後开始支援ho...
在粗浅的看过这一章时,觉得 Vue 真的有好多功能啊,目前的我似乎还是没办法很熟用 Vue 的每项语...
前言 《世说新语》提到:「覆巢之下,复有完卵乎?」放在交易市场也是如此。当整体趋势向下,再好的公司也...
Reverse 1.Transformation:考unicode 载下来的档案,看起来编码错误 用...
第九天,打完疫苗已经22小时,目前只有接种处抬手会酸痛,目前还没感受到其他副作用。不过头已经开始有点...