如何使用jackson反序列化到Kotlin集合

Mar*_*vin 17 json jackson kotlin

示例代码我想要的:

data class D(val a: String, val b: Int)
val jsonStr = """[{"a": "value1", "b": 1}, {"a": "value2", "b":"2}]"""
// what I need
val listOfD: List<D> = jacksonObjectMapper().whatMethodAndParameter?
Run Code Online (Sandbox Code Playgroud)

Jay*_*ard 30

使用Jackson Kotlin Module 当前版本,如果您导入完整的模块包或特定的扩展功能,您将拥有所有可用的扩展方法.如:

import com.fasterxml.jackson.module.kotlin.*  
val JSON = jacksonObjectMapper()  // keep around and re-use
val myList: List<String> = JSON.readValue("""["a","b","c"]""")
Run Code Online (Sandbox Code Playgroud)

因此,Kotlin的Jackson Module将推断出正确的类型,并且您不需要TypeReference实例.

所以你的情况(稍微重命名并修复了数据类和JSON):

import com.fasterxml.jackson.module.kotlin.readValue

data class MyData(val a: String, val b: Int)
val JSON = jacksonObjectMapper()  

val jsonStr = """[{"a": "value1", "b": 1}, {"a": "value2", "b": 2}]"""
val myList: List<MyData> = JSON.readValue(jsonStr)
Run Code Online (Sandbox Code Playgroud)

您还可以使用以下表单:

val myList = JSON.readValue<List<MyData>>(jsonStr)
Run Code Online (Sandbox Code Playgroud)

如果没有导入,则会出现错误,因为找不到扩展功能.

  • 请注意,在这种情况下,只需导入给定的扩展函数就足够了,而不是整个包:“import com.fasterxml.jackson.module.kotlin.readValue”。 (2认同)

des*_*eim 14

TL; DR

与杰克逊2.6.3-2一样,@ jason-minard建议并简单地使用:

import com.fasterxml.jackson.module.kotlin.readValue

val listOfD: List<D> = jacksonMapper.readValue(jsonStr)
Run Code Online (Sandbox Code Playgroud)

细节

虽然你需要kotlin jackson模块来反序列化没有注释的数据类,但Kotlin对反序列化没什么特别之处.

也就是说,在您的情况下,它将需要完整的具体类型信息,以便跟踪列表的通用参数(D); 否则(例如,如果你使用readValue(jsonStr, List::class.java))杰克逊只会把它看作一个被删除的类型(即List)(如Kotlin明确的那样)并将其反序列化为a List<Map<String, String>>,而不知道它必须构造Ds.这是工作围绕使用的匿名子类TypeReference在Java中,这样杰克逊可以完全访问物化的类型在运行时反序列化.

将Jackson Java代码字面翻译为Kotlin,以下因此实现了您想要的(并且由@​​eski评论,请注意您的示例中的JSON无效):

val jacksonMapper = ObjectMapper().registerModule(KotlinModule())

val jsonStr = """[{"a": "value1", "b": 1}, {"a": "value2", "b":2}]"""
val listOfD: List<D> = jacksonMapper.readValue(jsonStr, object : TypeReference<List<D>>(){})

assertEquals(listOf(D("value1", 1), D("value2", 2)), listOfD)
Run Code Online (Sandbox Code Playgroud)

这有点冗长和丑陋,所以你可以把它隐藏在Kotlin(扩展)函数中(特别是如果你打算多次使用它):

inline fun <reified T> ObjectMapper.readValue(json: String): T = readValue(json, object : TypeReference<T>(){})
Run Code Online (Sandbox Code Playgroud)

这将允许你然后只是打电话:

val listOfD: List<D> = jacksonMapper.readValue(jsonStr)
Run Code Online (Sandbox Code Playgroud)

这就是2.6.3-2jackson Kotlin模块中包含的内容.