我如何从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有一些事情会成为一个问题。 一个是,你如何获得一些图书馆想要了解的Class
, TypeToken
, TypeReference
或其他专业类。 另一个是他们如何构造并不总是具有默认构造函数或不可变的类。
对于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::class
或SomeOtherClass::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)