0

我正在构建一个多平台 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?

4

0 回答 0