为了演示,我们新建一个简单的数据类Person
数据类Person
data class Person(var name: String = "", var age: Int = 0)
json数据反序列化为普通对象
使用Gson将Json数据直接转成普通实体类很简单,如下
Gson().fromJson<Person>(personsJson,Person::class.java)
json数据反序列化为集合
有的时候,我们可能需要直接将一段json数据转成一个List
例如下面的json数据。
[{"age":1,"name":"yzq"},{"age":2,"name":"yzq"},{"age":3,"name":"yzq"},{"age":4,"name":"yzq"},{"age":5,"name":"yzq"},{"age":6,"name":"yzq"},{"age":7,"name":"yzq"},{"age":8,"name":"yzq"},{"age":9,"name":"yzq"},{"age":10,"name":"yzq"}]
我们先来看看Gson的源码说明,注释已经告诉我们了需要用到TypeToken
将json直接转为list,通过TypeToken来实现,代码如下
private lateinit var newPersons: ArrayList<Person>
val listType = object : TypeToken<ArrayList<Person>>() {}.type
newPersons = Gson().fromJson(personsJson, listType)
我们来打印下反序列化后的newPersons
[Person(name=yzq, age=1), Person(name=yzq, age=2), Person(name=yzq, age=3), Person(name=yzq, age=4), Person(name=yzq, age=5), Person(name=yzq, age=6), Person(name=yzq, age=7), Person(name=yzq, age=8), Person(name=yzq, age=9), Person(name=yzq, age=10)]
这样我们就完成了直接将json数据转为集合。
封装以及运行期泛型擦除的坑
在日常开发中,我们一般会封装一个通用的GsonUtil在简化代码。
对于直接将json转list,我们可能会这样写:
package com.yzq.kotlin.demo
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
/** * @description: Gson 工具类 * @author : yuzhiqiang (zhiqiang.yu.xeon@gmail.com) */
object GsonUtil {
val gson: Gson = GsonBuilder()
.serializeNulls()
.setLenient()
.create()
fun <T> fromJson(json: String): T {
return gson.fromJson(json, object : TypeToken<T>() {
}.type)
}
fun toJson(src: Any): String {
return gson.toJson(src)
}
}
然后这样用:
val jsonArr =
"[{\"age\":1,\"name\":\"yzq\"},{\"age\":2,\"name\":\"yzq\"},{\"age\":3,\"name\":\"yzq\"},{\"age\":4,\"name\":\"yzq\"},{\"age\":5,\"name\":\"yzq\"},{\"age\":6,\"name\":\"yzq\"},{\"age\":7,\"name\":\"yzq\"},{\"age\":8,\"name\":\"yzq\"},{\"age\":9,\"name\":\"yzq\"},{\"age\":10,\"name\":\"yzq\"}]"
val personList = GsonUtil.fromJson<ArrayList<Person>>(jsonArr)
println("personList = ${
personList}")
然后我们运行看一下结果:
可以看到,正常打印了,好像没有什么问题。那我们再加一点代码,如下:
val jsonArr =
"[{\"age\":1,\"name\":\"yzq\"},{\"age\":2,\"name\":\"yzq\"},{\"age\":3,\"name\":\"yzq\"},{\"age\":4,\"name\":\"yzq\"},{\"age\":5,\"name\":\"yzq\"},{\"age\":6,\"name\":\"yzq\"},{\"age\":7,\"name\":\"yzq\"},{\"age\":8,\"name\":\"yzq\"},{\"age\":9,\"name\":\"yzq\"},{\"age\":10,\"name\":\"yzq\"}]"
val personList = GsonUtil.fromJson<ArrayList<Person>>(jsonArr)
println("personList = ${
personList}")
personList.forEach {
println(it.name)
}
我们只是在将json转成list后对list做遍历打印值,运行看看代码:
结果发现报错了,报错信息如下
com.google.gson.internal.LinkedTreeMap cannot be cast to com.yzq.kotlin.demo.Person
原因是泛型类型在运行时会被擦除,导致了该问题。
那我们又不想每次将json转list都去写 object : TypeToken<ArrayList>() {}.type 这样的代码怎么办。
val fromJson = Gson().fromJson<Any>(jsonArr, object : TypeToken<ArrayList<Person>>() {
}.type)
我们可以使用kotlin内联函数中的reified
来解决该问题。
reified:具体化的类型参数,可以在运行时也访问到泛型的具体类型。
那我们就将上面那个toJosn方法改成这样:
inline fun <reified T> fromJson(json: String): T {
return gson.fromJson(json, object : TypeToken<T>() {
}.type)
}
然后再来跑一遍代码:
可以看到,没有报错,而且打印的personList中能够明确的看到是Person类型,上面那个并没有Person类型的显示,那这样一来,我们fromJson代码写起来就简洁许多了
下面是我日常开发用的代码,很简单,需要可以参考。
package com.yzq.kotlin.demo
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
/** * @description: Gson 工具类 * @author : yuzhiqiang (zhiqiang.yu.xeon@gmail.com) */
object GsonUtil {
val gson: Gson = GsonBuilder()
.serializeNulls()
.setLenient()
.create()
private val prettyGson: Gson = GsonBuilder()
.serializeNulls()
.setPrettyPrinting()
.setLenient()
.create()
fun <T> fromJson(json: String, classOfT: Class<T>): T {
return gson.fromJson(json, classOfT)
}
inline fun <reified T> fromJson(json: String): T {
return gson.fromJson(json, object : TypeToken<T>() {
}.type)
}
fun toJson(src: Any): String {
return gson.toJson(src)
}
fun toPrettyJson(src: Any): String {
return prettyGson.toJson(src)
}
fun toJson(src: Any, typeOfSrc: Type): String {
return gson.toJson(src, typeOfSrc)
}
}
日常开发中,使用Gson时都会有一些小技巧,让我们使用Gson更加简洁。感兴趣的可以看下面这片博客
本篇博客就是这些,希望对你有帮助。
如果你觉得本文对你有帮助,麻烦动动手指顶一下,算是对本文的一个认可,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!
今天的文章Gson直接将json转list示例 (TypeToken)以及通过内联函数结合reified简化代码分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/9532.html