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

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

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

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

我试过以下,但他们不工作。

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

我如何从types名称中获得一个java类?

以下工作如期:

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

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

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

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

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

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

对于jackson来说,一个模块是专门为了涵盖这些案例而建立 这是在@ miensol的答案中提到的。 他展示了一个类似于的例子:

 import com.fasterxml.jackson.module.kotlin.* // added for clarity val operationalResult: OperationalResult = mapper.readValue(""{"result":"5"}""") 

这实际上是调用由Kotlin模块添加到ObjectMapper的内联扩展函数,它使用推断出的types来获取泛化generics(可用于内联函数),以完成告诉Jackson有关数据types所需的任何操作。 它会在幕后创建一个Jackson TypeReference ,并将其传递给Jackson。 这是函数的来源:

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

你可以很容易地编写相同的代码,但是模块有更多的这些帮助者为你做这个工作。 另外它还可以为你调用非默认的构造函数和静态工厂方法。 在Jackson 2.8。+中,它也可以更加智能地处理可空性和默认方法参数(允许在JSON中缺少值,因此使用默认值)。 没有这个模块,你很快就会发现新的错误。

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

 val myTypeRef = object: TypeReference() {} 

这段代码创建了一个类的匿名实例(通过一个对象expression式 ),该TypeRefrence具有指定的generics类的超typesTypeRefrence 。 然后Javareflection可以查询这些信息。

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

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

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

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