user866364
user866364

Reputation:

How to make jackson accept generic on readvalue?

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

Answers (1)

Nicolas
Nicolas

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

Related Questions