1

Kotlin Code

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)

result error

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

How can I modify my code to fix this?

Federico klez Culloca
  • 26,308
  • 17
  • 56
  • 95
ChaoYang
  • 13
  • 2

1 Answers1

1

As it appears from OP response in question's comment section using reified helped to solve the problem. Original source code had to be modified in order to make use of reified keyword. Functions are inlined and extension function for Gson is implemented to avoid the use of TypeToken class.

Here is great SO answer: What is reified, how it works and when to use it?

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)
Jenea Vranceanu
  • 4,530
  • 2
  • 18
  • 34
  • Could you reproduced the error of the OP? I couldn't. Actually, `reified` shouldn't be needed here since OP's code does not access the type. – Willi Mentzel Aug 20 '20 at 13:51
  • 1
    @WilliMentzel, no I actually could not reproduce the issue. Probably it could be the issue related to a specific version of Gson library (or maybe the issue was in some other place and the question's content is incorrect). What I did is just replaced `TypeToken` with inlined function with reified generic type as they both deal with type erasure. It was easy to send an example and since OP commented on that solution as helpful I decided to post it as an answer. – Jenea Vranceanu Aug 20 '20 at 15:21
  • 1
    "it could be the issue related to a specific version of Gson library (or maybe the issue was in some other place and the question's content is incorrect)" true, but I think using a reified type is better in the end than to use `TypeToken`. So good idea! it is just unfortunate that the problem can't be reproduced with what is given in the question. :( – Willi Mentzel Aug 20 '20 at 16:33