Gson直接将json转list示例 (TypeToken)以及通过内联函数结合reified简化代码

Gson直接将json转list示例 (TypeToken)以及通过内联函数结合reified简化代码为了演示,我们新建一个简单的数据类Person数据类PersondataclassPerson(varname:String="",varage:Int=0)json数据反序列化为普通对象使用Gson将Json数据直接转成普通实体类很简单,如下Gson().fromJson<Person>(personsJson,Person::class.java…

为了演示,我们新建一个简单的数据类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 来解决该问题。

Kotlin 内联函数官方文档

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使用的一些小技巧

本篇博客就是这些,希望对你有帮助。


如果你觉得本文对你有帮助,麻烦动动手指顶一下,算是对本文的一个认可,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!

今天的文章Gson直接将json转list示例 (TypeToken)以及通过内联函数结合reified简化代码分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/9532.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注