如何使用Gson通过泛型类类型将JSON数组字符串反序列化为对象模型?
问题描述
我写了一个Kotlin泛型函数,通过传入目标类的Class类型来把JSON字符串反序列化为对应对象,单个对象场景下正常工作:
fun <T> deserializeJsonStr(jsonString: String, dataClassType: Class<T>): T? { var ret: T? = Gson().fromJson<T>(jsonString, dataClassType) return ret }
比如针对TestData1类和单个对象的JSON:
// 数据模型 class TestData1 { var userId = 0 var id = 0 var title: String? = null var body: String? = null } // JSON字符串 { "userId": 1, "id": 3, "title": "the title", "body": "the body" } // 调用函数 val clazz: Class<TestData1> = TestData1::class.java val theTestData1 = deserializeJsonStr(jsonString, clazz)
能正常得到填充好的TestData1对象。但遇到JSON数组时,想要反序列化为ArrayList<TestData1>,尝试传递Class类型时编译失败:
// 编译报错 val clazz: Class<ArrayList<TestData1>> = ArrayList<TestData1>::class.java val theTestData1 = deserializeJsonStr(jsonString, clazz)
用ArrayList<>::class.java也无法通过编译,请问该怎么处理JSON数组的反序列化,或者说如何获取符合要求的ArrayList<TestData1>对应的Class类型?
解决方案
1. 编译失败的原因
Java/Kotlin存在泛型类型擦除机制,运行时ArrayList<TestData1>和ArrayList<String>的Class对象完全相同(都是ArrayList::class.java),无法直接获取带泛型参数的Class<ArrayList<TestData1>>,因此强转操作会触发编译错误。
2. 两种可行解决方式
方式一:修改函数,使用Gson的TypeToken保留泛型信息
Gson提供了TypeToken来规避泛型类型擦除问题,调整原函数支持该类型即可:
fun <T> deserializeJsonStr(jsonString: String, typeToken: TypeToken<T>): T? { return Gson().fromJson(jsonString, typeToken.type) }
调用时通过匿名内部类创建TypeToken指定泛型类型:
val typeToken = object : TypeToken<ArrayList<TestData1>>() {} val dataList = deserializeJsonStr(jsonString, typeToken)
方式二:先反序列化为数组,再转成ArrayList
如果不想修改原函数,可以利用数组类型信息不被完全擦除的特性,先反序列化为TestData1数组,再转换为ArrayList:
// 反序列化为TestData1数组 val arrayClazz: Class<Array<TestData1>> = Array<TestData1>::class.java val dataArray = deserializeJsonStr(jsonString, arrayClazz) // 转换为ArrayList val dataList = dataArray?.toCollection(ArrayList())
内容的提问来源于stack exchange,提问作者lannyf
相关产品推荐
相关产品推荐

