我想要的示例代码:
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?
答案 0 :(得分:26)
使用Jackson Kotlin模块current versions,如果您导入完整的模块包或特定的扩展功能,您将拥有所有可用的扩展方法。如:
import com.fasterxml.jackson.module.kotlin.*
val JSON = jacksonObjectMapper() // keep around and re-use
val myList: List<String> = JSON.readValue("""["a","b","c"]""")
因此,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)
您还可以使用以下表单:
val myList = JSON.readValue<List<MyData>>(jsonStr)
如果没有导入,您将收到错误,因为找不到扩展功能。
答案 1 :(得分:12)
杰克逊2.6.3-2
做@ jason-minard建议并简单地使用:
import com.fasterxml.jackson.module.kotlin.readValue
val listOfD: List<D> = jacksonMapper.readValue(jsonStr)
对于deserializing collections来说Kotlin wrt并没有什么特别之处,尽管你需要kotlin jackson module来反序列化没有注释的数据类。
即,在您的情况下,它将需要完整的具体类型信息,以便跟踪列表的通用参数(D
);否则(例如,如果你使用readValue(jsonStr, List::class.java)
)杰克逊只会将其视为已擦除类型(即List
)(如Kotlin所示)并将其反序列化为List<Map<String, String>>
,但不知道它有构建D
s。这是worked around在Java中使用TypeReference
的匿名子类,以便Jackson可以在运行时访问完整的已知类型以反序列化。
将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)
虽然这有点冗长和丑陋,所以你可以将它隐藏在Kotlin(扩展)功能中(特别是如果你打算多次使用它):
inline fun <reified T> ObjectMapper.readValue(json: String): T = readValue(json, object : TypeReference<T>(){})
这将允许您随后调用:
val listOfD: List<D> = jacksonMapper.readValue(jsonStr)
这就是2.6.3-2
杰克逊Kotlin模块中包含的内容。
答案 2 :(得分:0)
如果您没有通用内容的类型,例如下面的示例中的<MyData>
:
val value = context.readValue<List<MyData>>(parser, valueType)
您不仅可以实现JsonSerialzier
,而且还可以实现ContextualDeserializer
,例如下面的代码示例(基于Java中的answer):
class GenericListDeserializer : JsonDeserializer<List<*>>(), ContextualDeserializer {
private var valueType: JavaType? = null
override fun createContextual(ctxt: DeserializationContext, property: BeanProperty): JsonDeserializer<List<*>> {
val wrapperType = property.type
val valueType = wrapperType.containedType(0)
val deserializer = GenericListDeserializer()
deserializer.valueType = valueType
return deserializer
}
override fun deserialize(parser: JsonParser, context: DeserializationContext): List<*> {
val value :Any? = context.readValue(parser, valueType)
return listOf(value)
}
}