反序列化以下JSON的正确语法是什么:
[ {
"id" : "1",
"name" : "Blues"
}, {
"id" : "0",
"name" : "Rock"
} ]
我试过了:
//Works OK
val dtos = mapper.readValue(json, List::class.java)
不管我怎么想:
val dtos : List<GenreDTO> = mapper.readValue(json,
List<GenreDTO>::class.java)
上面的语法不正确,并给出了:only classes are allowed on the left hand side of a class literal
发布于 2016-01-11 11:56:22
注意:来自@IRus的答案也是正确的,它在我写这篇文章的同时被修改,以填写更多细节。
您应该使用Jackson + Kotlin module,否则当您没有默认构造函数时,在反序列化为Kotlin对象时会遇到其他问题。
您的第一个代码示例:
val dtos = mapper.readValue(json, List::class.java)
返回一个推断的List<*>
类型,因为您没有指定更多的类型信息,并且它实际上是一个List<Map<String,Any>>
,它并不是真正的“工作正常”,但不会产生任何错误。它是不安全的,没有类型。
第二个代码应该是:
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
val mapper = jacksonObjectMapper()
// ...
val genres: List<GenreDTO> = mapper.readValue(json)
你在赋值的右边不需要任何东西,Jackson的Kotlin模块将具体化泛型并在内部为Jackson创建TypeReference
。请注意readValue
导入,您需要它或.*
才能使com.fasterxml.jackson.module.kotlin
包具有执行所有魔术功能的扩展函数。
另一种略微不同的选择也有效:
val genres = mapper.readValue<List<GenreDTO>>(json)
没有理由不使用扩展功能和Jackson的附加模块。它很小,并且解决了其他问题,这些问题需要你跳过一圈来创建一个默认的构造函数,或者使用一堆注释。有了这个模块,你的类可以是普通的Kotlin (可选的是data
类):
class GenreDTO(val id: Int, val name: String)
发布于 2016-01-11 08:49:00
您得到的错误是关于以下表达式的:
List<GenreDTO>::class.java
由于jvm处理泛型的方式,List<GenreDTO>
没有单独的类,因此编译器会抱怨。类似地,在Java中不会编译以下代码:
List<GenreDTO>.getClass()
下面是一个将正确反序列化该列表的示例:
val value:List<GenreDTO> = mapper.readValue(json, object : TypeReference<List<GenreDTO>>() {})
正如@JaysonMinard所指出的,您可以使用jackson-module-kotlin来简化调用,以:
val genres: List<GenreDTO> = mapper.readValue(json)
// or
val genres = mapper.readValue<List<GenreDTO>>(json)
这要归功于reified type parameters
。请考虑查看Extensions
以了解详细信息。
发布于 2016-01-11 08:46:57
下面的代码对我来说很好用:
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
val json = """[ {
"id" : "1",
"name" : "Blues"
}, {
"id" : "0",
"name" : "Rock"
} ]"""
data class GenreDTO(val id: Int, val name: String)
val mapper = ObjectMapper().registerKotlinModule()
fun main(args: Array<String>) {
val obj: List<GenreDTO> = mapper.readValue(json)
obj.forEach {
println(it)
}
}
这是由于jackson-kotlin-module (使用reified泛型)中定义的扩展函数:
public inline fun <reified T: Any> ObjectMapper.readValue(content: String): T = readValue(content, object: TypeReference<T>() {})
感谢@JaysonMinard通知我这件事。
输出:
GenreDTO(id=1, name=Blues)
GenreDTO(id=0, name=Rock)
https://stackoverflow.com/questions/34716697
复制