关于泛型导致 ClassCastException LinkedTreeMap cannot be cast to Any

About generics causing ClassCastException LinkedTreeMap cannot be cast to Any

Kotlin 代码

class ResponseBody<T> {
    var code : Int = 0
    var msg : String = ""
    var data : T? = null
}

class ExampleT {
    var text: String = ""
    // var list: List<String>? = null
}

// utils fun
fun <T> request(json : String) : ResponseBody<T>? {
    val gson = Gson()
    var responseBody: ResponseBody<T>? = null
    if (json.contains("code") && json.contains("data")) {         
         responseBody = gson.fromJson(json, object : TypeToken<ResponseBody<T>>() {}.type)
    } else {
         val tdata : T = gson.fromJson(json, object : TypeToken<T>() {}.type)
         responseBody = ResponseBody()
         responseBody.code = 200
         responseBody.msg = "success"
         responseBody.data = tdata
    }
    return responseBody
}

// main
val json : String = "{\"code\":200,\"msg\":\"success\",\"data\":{\"text\":\"text text text\"}}"
// val json : String = "{\"text\":\"text text text\"}"
val responseBody : ResponseBody<ExampleT> = request(json)

结果错误

ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to ExampleT

如何修改我的代码来解决这个问题?

从问题评论部分的 OP 回复来看,使用 reified 有助于解决问题。必须修改原始源代码才能使用 reified 关键字。内联函数并实现 Gson 的扩展函数以避免使用 TypeToken class.

这是很棒的答案:

class ResponseBody<T> {
    var code : Int = 0
    var msg : String = ""
    var data : T? = null
}

class ExampleT {
    var text: String = ""
    // var list: List<String>? = null
}

// utils fun
inline fun <reified T> request(json : String) : ResponseBody<T> {
    val gson = Gson()
    var responseBody: ResponseBody<T>? = null
    if (json.contains("code") && json.contains("data")) {
        return gson.fromJson(json)
    } else {
        val tdata : T = gson.fromJson(json)
        responseBody = ResponseBody()
        responseBody.code = 200
        responseBody.msg = "success"
        responseBody.data = tdata
    }
    return responseBody
}

inline fun <reified T> Gson.fromJson(json: String): T {
    return fromJson(json, T::class.java)
}

// main
val json : String = "{\"code\":200,\"msg\":\"success\",\"data\":{\"text\":\"text text text\"}}"
// val json : String = "{\"text\":\"text text text\"}"
val responseBody : ResponseBody<ExampleT> = request(json)