我正在构建一个多平台 JSON 库作为原型,以了解如何构建事物。
目前我有这个扩展函数可以从 JSON 数组转换为对象列表。
inline fun <reified T : Any> String.fromJsonList() : List<T> =
provider.fromJsonList(this, T::class)
为 Jackson 实现这个接口相当简单:
class JvaasJackson : JsonProvider {
val mapper = ObjectMapper();
...
override fun <T : Any> fromJsonList(input: String, type: KClass<T>): List<T> {
return mapper.readValue(input, mapper.typeFactory.constructCollectionType(List::class.java, type.java)) ?: listOf()
}
}
现在我正在尝试对 Gson 做同样的事情:
class JvaasGson : JsonProvider {
val gsonNormal = com.google.gson.Gson()
val gsonPretty = com.google.gson.GsonBuilder().setPrettyPrinting().create()
...
override fun <T : Any> fromJsonList(input: String, type: KClass<T>): List<T> {
TODO("fix this")
}
}
查看 Java 中的其他答案,这似乎是要遵循的模式:
Type listType = new TypeToken<List<MyModel>>(){}.getType();
List<MyModel> myModelList = gson.fromJson(jsonArray, listType);
我的 Kotlin 等效失败:
val listType = object : TypeToken<List<T>>() {}.type
val myModelList = gsonNormal.fromJson<List<T>>(input, listType) ?: listOf()
和:
java.lang.ClassCastException:java.util.ArrayList 无法转换为 [Ljava.lang.Object;
这个:
val listType = object : TypeToken<ArrayList<T>>() {}.type
val myModelList = gsonNormal.fromJson(input, listType) as ArrayList<T>
和这个:
val listType = object : TypeToken<ArrayList<T>>() {}.type
val myModelList = gsonNormal.fromJson<ArrayList<T>>(input, listType)
失败:
java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap 无法转换为 io.jvaas.integration.gson.SampleClass
SampleClass
的类型在哪里T
如果我删除类型并打印结果
val listType = object : TypeToken<ArrayList<T>>() {}.type
val list= gsonNormal.fromJson<Any>(input, listType)
println(list)
println(list::class)
println(list::class.java)
我看到了正确的数据:
[{blah1=文本,blah2=123.0,blah3=567.0},{blah1=文本,blah2=123.0,blah3=567.0}]
类 java.util.ArrayList
类 java.util.ArrayList
打印出该 ArrayList 的第一项,但是我看到它不是 SampleClass 类型,而是 LinkedTreeMap
println((list as List<T>).first()::class)
com.google.gson.internal.LinkedTreeMap 类
将该列表中的每个项目转换为字符串,然后将每个单独的 JSON 块转换为对象似乎可行,但看起来很 hacky
override fun <T : Any> fromJsonList(input: String, type: KClass<T>): List<T> {
val listType = object : TypeToken<ArrayList<*>>() {}.type
val list= gsonNormal.fromJson<List<Any>>(input, listType) ?: listOf<Any>()
val results = mutableListOf<T>()
list.forEach { item ->
results.add(gsonNormal.fromJson(item.toString(), type.java))
}
return results
}
有没有更好的方法来做到这一点?还是 Gson 总是将更复杂的 JSON 数据转换为 TreeMaps 和 LinkedTreeMaps?