问题原因
虽然ObjectMapper.treeToValue
是一个带有具体化泛型参数的 Kotlin 内联扩展函数(这意味着泛型在运行时被保留),它调用 JavaObjectMapper.treeToValue(TreeNode, Class<T>)
方法。传递的值作为Class<T>
将丢失泛型类型的泛型类型信息,例如List<Comment>
,因为类型擦除。
So treeToValue
可用于:
mapper.treeToValue<Comment>(commentNode)
但不适用于:
mapper.treeToValue<List<Comment>>(commentsNode)
另请注意ObjectMapper
包含多个方法@SuppressWarnings
注解,这会导致一些问题不是出现在编译时,而是出现在运行时。
解决方案1 - 使用convertValue()
这是最好的解决方案。它使用了 Kotlin 扩展函数ObjectMapper.convertValue
.
val commentsNode = mapper.readTree(fullJsonContent).get(0).get("Comments")
val comments = mapper.convertValue<List<Comment>>(commentsNode)
解决方案 2 - 使用 ObjectReader
该解决方案不使用jackson-module-kotlin
扩展功能。
val reader = mapper.readerFor(object : TypeReference<List<Comment>>() {})
val comments: List<Comment> = reader.readValue(commentsNode)
解决方案 3 - 在地图中反序列化
Because treeToValue
(Kotlin 扩展函数)确实适用于非泛型类型,您可以首先获取 JsonNode 列表形式的节点,然后将每个 JsonNode 映射到 Comment。
但麻烦的是不能简单地返回mapper.treeToValue(it)
,因为这会导致类型推断编译错误。
val commentsNode = mapper.readTree(fullJsonContent).get(0).get("Comments")
val comments = commentsNode.elements().asSequence().toList().map {
val comment: Comment = mapper.treeToValue(it)
comment
}