首页 > 解决方案 > 如何让杰克逊接受 readvalue 的泛型?

问题描述

我正在对一段糟糕的代码进行一些重构,因为我有非常相似的函数:

    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)

这些行之间的唯一区别是 call 的返回类型mapper.readValue(httpResponse)。基于此,我编写了一个用于两种场景的新函数:

    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);
    }

问题是:我不能使用“T”作为具体类型参数。如何编写一个将“通用”值传递给杰克逊的函数?

标签: kotlinjackson

解决方案


由于类型擦除,泛型类型在运行时丢失。这就是为什么不能使用Twith readValue,因为T仅用于确保编译时类型安全,但在运行时不存在。

为了解决这个问题,你可以让你的函数inline和泛型类型参数reified,所以类型类将在调用站点获得:

inline fun <reified T> test(value: String): T {
    return mapper.readValue(value, T::class.java)
}

或者,如果您使用 Jackson Kotlin 模块:

inline fun <reified T> test(value: String): T {
    return mapper.readValue<T>(value)
}

我稍微简化了你的用例,但它的工作原理是一样的。

进一步阅读:


推荐阅读