Reputation:
I'm doing some refactoring in a awful code because I have functions that are very similar:
fun getLogin(username: String) {
val uri = buildURI(BASE_URI, ApiRoute.GET_LOGIN.route, username)
val httpResponse = execRequest(uri, HttpMethod.GET)
val login: LoginResponse = mapper.readValue(httpResponse)
fun getUser(username: String) {
val uri = buildURI(BASE_URI, ApiRoute.GET_LOGIN.route, username)
val httpResponse = execRequest(uri, HttpMethod.GET)
val login: userResponse = mapper.readValue(httpResponse)
The only difference between those lines is the return type of call mapper.readValue(httpResponse)
. Based on that, I have wrote a new function to be used in both scenarios:
fun <T> getEvent(value: String, eventType: EventType): T {
val uri = buildURI(BASE_URI, eventType.route, value)
val httpResponse = execRequest(uri, HttpMethod.GET)
return mapper.readValue(httpResponse);
}
The problem is: I cannot use 'T' as reified type parameter. How can I wrote a function that pass a "generic" value to jackson?
Upvotes: 0
Views: 547
Reputation: 7121
Generic type is loss at runtime due to type erasure. This is why you can't use T
with readValue
, because T
is used only to ensure compile time type safety, but doesn't exist at runtime.
To solve this, you can make your function inline
and the generic type parameter reified
, so the type class will be obtained at the call site:
inline fun <reified T> test(value: String): T {
return mapper.readValue(value, T::class.java)
}
Or if you use the Jackson Kotlin module:
inline fun <reified T> test(value: String): T {
return mapper.readValue<T>(value)
}
I simplified your use case a little, but it's works the same.
Further reading:
Upvotes: 2