首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何使用Kotlin + Jackson将JSON反序列化为List<SomeType>?

如何使用Kotlin + Jackson将JSON反序列化为List<SomeType>?
EN

Stack Overflow用户
提问于 2016-01-11 16:08:09
回答 3查看 35.8K关注 0票数 28

反序列化以下JSON的正确语法是什么:

代码语言:javascript
代码运行次数:0
运行
复制
[ {
  "id" : "1",
  "name" : "Blues"
}, {
  "id" : "0",
  "name" : "Rock"
} ]

我试过了:

代码语言:javascript
代码运行次数:0
运行
复制
//Works OK
val dtos  = mapper.readValue(json, List::class.java)

不管我怎么想:

代码语言:javascript
代码运行次数:0
运行
复制
val dtos : List<GenreDTO>  = mapper.readValue(json, 
    List<GenreDTO>::class.java)

上面的语法不正确,并给出了:only classes are allowed on the left hand side of a class literal

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-01-11 19:56:22

注意:来自@IRus的答案也是正确的,它在我写这篇文章的同时被修改,以填写更多细节。

您应该使用Jackson + Kotlin module,否则当您没有默认构造函数时,在反序列化为Kotlin对象时会遇到其他问题。

您的第一个代码示例:

代码语言:javascript
代码运行次数:0
运行
复制
val dtos  = mapper.readValue(json, List::class.java)

返回一个推断的List<*>类型,因为您没有指定更多的类型信息,并且它实际上是一个List<Map<String,Any>>,它并不是真正的“工作正常”,但不会产生任何错误。它是不安全的,没有类型。

第二个代码应该是:

代码语言:javascript
代码运行次数:0
运行
复制
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包具有执行所有魔术功能的扩展函数。

另一种略微不同的选择也有效:

代码语言:javascript
代码运行次数:0
运行
复制
val genres = mapper.readValue<List<GenreDTO>>(json)

没有理由不使用扩展功能和Jackson的附加模块。它很小,并且解决了其他问题,这些问题需要你跳过一圈来创建一个默认的构造函数,或者使用一堆注释。有了这个模块,你的类可以是普通的Kotlin (可选的是data类):

代码语言:javascript
代码运行次数:0
运行
复制
class GenreDTO(val id: Int, val name: String)
票数 43
EN

Stack Overflow用户

发布于 2016-01-11 16:49:00

您得到的错误是关于以下表达式的:

代码语言:javascript
代码运行次数:0
运行
复制
List<GenreDTO>::class.java

由于jvm处理泛型的方式,List<GenreDTO>没有单独的类,因此编译器会抱怨。类似地,在Java中不会编译以下代码:

代码语言:javascript
代码运行次数:0
运行
复制
List<GenreDTO>.getClass()

下面是一个将正确反序列化该列表的示例:

代码语言:javascript
代码运行次数:0
运行
复制
val value:List<GenreDTO> = mapper.readValue(json, object : TypeReference<List<GenreDTO>>() {})

正如@JaysonMinard所指出的,您可以使用jackson-module-kotlin来简化调用,以:

代码语言:javascript
代码运行次数:0
运行
复制
val genres: List<GenreDTO> = mapper.readValue(json)
// or
val genres = mapper.readValue<List<GenreDTO>>(json)

这要归功于reified type parameters。请考虑查看Extensions以了解详细信息。

票数 13
EN

Stack Overflow用户

发布于 2016-01-11 16:46:57

下面的代码对我来说很好用:

代码语言:javascript
代码运行次数:0
运行
复制
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泛型)中定义的扩展函数:

代码语言:javascript
代码运行次数:0
运行
复制
 public inline fun <reified T: Any> ObjectMapper.readValue(content: String): T = readValue(content, object: TypeReference<T>() {})

感谢@JaysonMinard通知我这件事。

输出:

代码语言:javascript
代码运行次数:0
运行
复制
GenreDTO(id=1, name=Blues)
GenreDTO(id=0, name=Rock)
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34716697

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档