我正在使用GSON通过以下方式解析JSON:
var obj = Gson().fromJson( json, Array<MyDataModel>::class.java ).toList()
我希望能够通过以下方式通过方法传递数据类型:
fun convert( t : Any ) : Any
{
return Gson().fromJson( mockedResponse, t ).toList()
}
val model = convert( Array<MyDataModel>::class.java )
但是我得到了
None of the following functions can be called with the arguments supplied
我也尝试使用 Type 作为参数数据类型,但是仍然存在相同的错误。如何将DataType传递给我的convert方法?谢谢!
答案 0 :(得分:4)
这里发生了几件事。
首先,传递类型的传统方法是传递其KClass
对象(使用::type
或Class
对象(使用::type.class
)。
因此您可以将函数声明为:
fun convert(t: Class<*>): Any
但这会带来一个新问题:Gson().fromJson()
返回您指定类型的对象。在这种情况下,它可以是任何东西(因此*
),因此编译器不知道您是否可以在其上调用toList()
。
对此的一种解决方案是提供类型绑定,例如:
fun <T: Collection<U>, U> convert(t: Class<T>): List<U>
这指定您传递的类型必须是Collection
的某种实现,并且它返回具有相同元素类型的List
。而且由于Collection
有一个toList()
方法,所以一切正常。
但是,这不适用于您传递Array
类型的情况,因为数组没有toList()
方法。 ({Array
类型在Kotlin中有点尴尬。它们主要是为了与Java向后兼容; List
在许多方面都更好。)
您可以使用以上内容,并直接使用列表类型。但是,您将无法指定List元素类型:
fun <T: Collection<U>, U> convert(t: Class<T>): List<U> {
return Gson().fromJson(mockedResponse, t).toList()
}
val model: List<*> = convert(List::class.java)
因此,最好将toList()
放到函数中,而不要完全限制类型。这样,调用方可以进行所需的任何转换,从而保留元素类型:
fun <T> convert(t: Class<T>): T {
return Gson().fromJson(mockedResponse, t)
}
val model: List<MyDataModel> = convert(Array<MyDataModel>::class.java).toList()
作为最后的调整,我们可以使用Kotlin的另一种稍微整洁的方式来传递类型:使它们具体化。此替换在编译时完成,而不是在运行时完成,并且仅适用于inline
函数:
inline fun <reified T> convert(): T {
return Gson().fromJson(mockedResponse, T::class.java)
}
val model: List<MyDataModel> = convert<Array<MyDataModel>>().toList()
答案 1 :(得分:1)
恐怕您将不得不在此处使用泛型:
类似的东西:
inline fun <T, reified R>convert( t : T ) : R {
return Gson().fromJson(t, R::class.java )
}