我正在构建一个多平台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中的other answers,这似乎是遵循的模式:
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 = text,blah2 = 123.0,blah3 = 567.0},{blah1 = text,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类
将该列表中的每个项目转换为String,然后将JSON的每个单独的blob转换为对象似乎可行,但是看起来很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?