如何将JSON反序列化为与Kotlin + Jackson的List <SomeType>

什么是反序列化以下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

3 Solutions collect form web for “如何将JSON反序列化为与Kotlin + Jackson的List <SomeType>”

注: 从@ IRUS的答案也是正确的,它正在修改,同时我写这个来填补更多的细节。

您应该使用Jackson + Kotlin模块,否则当您没有默认构造函数时,您将有其他问题反序列化为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) 

以下代码适合我:

 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(使用了物化的泛型)里面定义的扩展函数:

  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) 

你得到的错误是关于下面的表达式:

 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找出细节。

  • 我如何从类型名称获取类名?
  • 为什么getMessage()是一个Exception类的Kotlin未解决的引用?
  • 从Java迁移到Kotlin
  • Kotlin中分号推理的规则是什么?
  • 将java类文件转换为kotlin会导致编译错误
  • 什么访问修饰符可测试辅助方法?
  • 返回块中的最后一个表达式
  • 匕首与Kotlin上的Mvp - Android
  • 如何在Kotlin中创建一个也是Java中不可变列表的不可变列表?
  • 从Kotlin任何显式继承 - 可以和它是如何做到的?
  • 无法减少kotlin中的布尔值列表
  • Kotlin language will be the best programming language for Android.