【问题标题】:kotlin, how to use Gson to parse a generic type is a function defined with generic typekotlin,如何使用 Gson 解析泛型类型是用泛型类型定义的函数
【发布时间】:2018-04-18 15:11:29
【问题描述】:

如果类类型是泛型类型'T',如何使用Gson进行解析?

拥有一个泛型类型的类,并且在其函数中将 json 字符串解析为运行时泛型类型“T”的任何内容。但是得到了

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.model.content

这不适用于泛型是 'T':

        val dataType = object : TypeToken<T>() {}.type
        val data = Gson().fromJson<T>(jsonStr, dataType)

这就是使用 'solid' 类类型 Content 为传入的 Handler&lt;Content&gt; 调用调用的方式,其中需要通用 'T' (IHandler&lt;T&gt;)

FetchRemoteDataCommand("https", “testcontent.com", "v2/content”,
    params,
    Handler<Content>).execute()

这是一个采用泛型类型的类:IHandler&lt;T&gt;,期望在运行时“T”应该是“solid”类型,即它应该是调用时的 Content 类型

class FetchRemoteDataCommand<T>(scheme: String, authority: String, path: String,
                         params: HashMap<String, String>,
                         dataReadyCb: IHandler<T>) {


val mBaseUrl = "$scheme://$authority/"
val mPath = path
val mParams = params
var mDataReadyListener = dataReadyCb

override fun dispose() {……}

override fun execute() {
    getRemoteData(object : Observer<ResponseBody> {
        override fun onNext(responseBody: ResponseBody) {

            val dataType = object : TypeToken<T>() {}.type
            val jsonStr = responseBody.string()
            val data = Gson().fromJson<T>(jsonStr, dataType)  ***//<=== throws***

            ///
            mDataReadyListener(data)  //<== suppose to pass back the pared data back
            ……
        }
        …………
    })
}

private fun getRemoteData(observer: Observer<ResponseBody>) : Unit {

    val service: IRemoteRepositoryService = ServiceFactory.createRetrofitService(
                          IRemoteRepositoryService::class.java, mBaseUrl)

    service.getRemoteData(mPath, mParams) 
           .subscribe(observer)

    }
 }

【问题讨论】:

    标签: generics kotlin gson


    【解决方案1】:

    get-generic-type-of-class-at-runtime 中从 Henning 和(Lin Yu Cheng 也有一个在运行时获取它的解决方案)得到想法 所以传入类类型而不是在运行时获取类型。

    class FetchRemoteDataCommand<T>(scheme: String, authority: String, path: String,
                         params: HashMap<String, String>,
                         dataReadyCb: IHandler<T>, handlerClassType: Class<T>) {
    
    
    val mBaseUrl = "$scheme://$authority/"
    val mPath = path
    val mParams = params
    var mDataReadyListener = dataReadyCb
    private val clazz: Class<T> = handlerClassType //findTypeArguments(this.javaClass)  <== some time return null???
    
    private fun findTypeArguments(t: Type) : Class<T> {
        return if (t is ParameterizedType) {
            val typeArgs = t.actualTypeArguments
            typeArgs[0] as Class<T>
        } else {
            val c = t as Class<*>
            findTypeArguments(c.genericSuperclass)
        }
    }
    
    fun getClassType(): Class<T> {
        return clazz
    }
    
    
    override fun execute() {
        getRemoteData(object : Observer<ResponseBody> {
            override fun onNext(responseBody: ResponseBody) {
    
                //val dataType = object : TypeToken<T>() {}.type
                //val jsonStr = responseBody.string()
                //val data = Gson().fromJson<T>(jsonStr, dataType)  ***//<=== throws***
    
    /// test generic type with the passed in class type instead of reflecting at runtime
                val responseRecieved = responseBody.string()
                val data = Gson().fromJson(responseRecieved, getClassType())
    
                ///
                mDataReadyListener(data)  //<== suppose to pass back the pared data back
            ……
        }
        …………
        })
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-21
      • 1970-01-01
      • 1970-01-01
      • 2018-06-02
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多