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

我试图反序列化一个Json字符串到一个类型为OperationResult<String>的对象,使用Jackson和Kotlin。

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

 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类?

以下工作如期:

 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 

而在杰克逊 – 科特林模块的帮助下,你甚至可以写:

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

当使用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数据类型所需的任何操作。 它会在幕后创建一个Jackson TypeReference ,并将其传递给Jackson。 这是函数的来源:

 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>() {} 

这段代码创建了一个类的匿名实例(通过一个对象表达式 ),该TypeRefrence具有指定的泛型类的超类型TypeRefrence 。 然后Java反射可以查询这些信息。

请小心使用Class直接,因为它消除泛型类型信息,所以使用SomeOtherClass::classSomeOtherClass::class.java都失去了泛型,应避免的事情,需要知道的事情。

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

您需要获取Class not KClass实例。 为了得到它,只需使用::class.java而不是::class

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