I am creating http json client. I am using Volley in combination with coroutines. I wanted to create generic http client so I can use it everywhere.
I have created generic extension method to parse JSON string into object.
inline fun <reified T>String.jsonToObject(exclusionStrategy: ExclusionStrategy? = null) : T {
val builder = GsonBuilder()
if(exclusionStrategy != null){
builder.setExclusionStrategies(exclusionStrategy)
}
return builder.create().fromJson(this, object: TypeToken<T>() {}.type)
}
Problem is that when I call this method I don’t get expected result. First call gives proper result. Object is initialized. But second call, where I use generic parameter which is passed to method, ends with exception “LinkedTreeMap can not be cast into Token”.
protected inline fun <reified T>sendRequestAsync(endpoint: String, data: Any?, method: Int, token: Token?): Deferred<T> {
return ioScope.async {
suspendCoroutine<T> { continuation ->
val jsonObjectRequest = HttpClient.createJsonObjectRequest(
endpoint,
data?.toJsonString(),
method,
Response.Listener {
//this call is successful and object is initialized
val parsedObject : HttpResponse<Token> = it.toString().jsonToObject()
//this call is not successful and object is not initialized properly
val brokenObject : HttpResponse<T> = it.toString().jsonToObject()
continuation.resume(brokenObject.response)
},
Response.ErrorListener {
continuation.resumeWithException(parseException(it))
},
token)
HttpClient.getInstance(context).addToRequestQueue(jsonObjectRequest)
}
}
}
Call of generic method.
fun loginAsync(loginData: LoginData): Deferred<Token> {
return sendRequestAsync("/tokens/", loginData, Request.Method.POST, null)
}
This is how httpresponse data class looks.
data class HttpResponse<T> (
val response: T
)
I saw a workaround here using Type::class.java but I don’t like this approach and I would like to use reified and inline keywords.
So please could someone give me any advice on this?
Thank you