如何从类型名称中获取类名?

时间:2016-09-07 18:40:53

标签: kotlin

我正在尝试使用Jackson和Kotlin将Json字符串反序列化为OperationResult<String>类型的对象。

我需要像这样构造一个类型对象:

val mapper : ObjectMapper = ObjectMapper();
val type : JavaType = mapper.getTypeFactory()
         .constructParametricType(*/ class of OperationResult */,, 
          /* class of String */);
val result : OperationResult<String> = mapper.readValue(
                  responseString, type);

我尝试了以下但是它们不起作用。

val type : JavaType = mapper.getTypeFactory()
            .constructParametricType(
             javaClass<OperationResult>, 
             javaClass<String>); // Unresolved javaClass<T>

val type : JavaType = mapper.getTypeFactory()
            .constructParametricType(
             OperationResult::class, 
             String::class);

如何从类型名称中获取java类?

3 个答案:

答案 0 :(得分:4)

您需要获取Class而不是KClass的实例。要获得它,只需使用::class.java代替::class

val type : JavaType = mapper.typeFactory.constructParametricType(OperationResult::class.java, String::class.java)

答案 1 :(得分:4)

当使用Jackson,GSON或其他实例化Kotlin对象的库时,Kotlin会有一些问题引起关注。一,是如何获得ClassTypeTokenTypeReference或其他某些图书馆想要了解的专业课程。另一个是他们如何构造并不总是具有默认构造函数的类,或者是不可变的。

对于杰克逊来说,专门为这些案件建立了一个模块。在@miensol的回答中提到了它。他展示了一个类似的例子:

import com.fasterxml.jackson.module.kotlin.*  // added for clarity

val operationalResult: OperationalResult<Long> = mapper.readValue(""{"result":"5"}""")

这实际上是调用Kotlin模块添加到ObjectMapper的内联扩展函数,它使用结果的推断类型获取已知的内联函数(可用于内联函数)来执行告诉Jackson所需的任何操作关于数据类型。它会在幕后为你创造一个杰克逊TypeReference并将其传递给杰克逊。这是该功能的来源:

inline fun <reified T: Any> ObjectMapper.readValue(content: String): T = readValue(content, object: TypeReference<T>() {})  

您可以轻松编写相同的代码,但模块中有大量的这些帮助程序可以为您完成此工作。此外,它还可以为您调用非默认构造函数和静态工厂方法。在Jackson 2.8。+中,它还可以更智能地处理可空性和默认方法参数(允许在JSON中缺少值,因此使用默认值)。没有该模块,您很快就会发现新的错误。

至于您对mapper.typeFactory.constructParametricType的使用,您应该使用TypeReference代替它,它更容易,并遵循与上述相同的模式。

val myTypeRef = object: TypeReference<SomeOtherClass>() {}

此代码创建一个类的匿名实例(通过object expression),其具有指定了您的泛型类的超级类型TypeRefrence。然后,Java反射可以查询此信息。

请小心使用Class,因为它会删除泛型类型信息,因此使用SomeOtherClass::classSomeOtherClass::class.java都会丢失泛型,对于需要了解它们的内容应该避免使用。

所以即使你可以在不使用Jackson-Kotlin模块的情况下逃脱一些事情,你很快就会遇到很多痛苦。而不是必须破坏你的Kotlin这个模块消除了这些类型的错误,让你以“Kotlin方式”做更多事情。

答案 2 :(得分:3)

以下按预期方式工作:

val type = mapper.typeFactory.constructParametricType(OperationalResult::class.java, String::class.java)
val operationalResult = mapper.readValue<OperationalResult<String>>("""{"result":"stack"}""", type)
println(operationalResult.result) // -> stack

使用com.fasterxml.jackson.core.type.TypeReference反序列化泛型类型的简单替代方法:

val operationalResult = mapper.readValue<OperationalResult<Double>>("""{"result":"5.5"}""",
        object : TypeReference<OperationalResult<Double>>() {})
println(operationalResult.result) // -> 5.5

借助jackson-kotlin-module你甚至可以写下:

val operationalResult = mapper.readValue<OperationalResult<Long>>("""{"result":"5"}""")
println(operationalResult.result)