Jackson Kotlin - Deserialize JsonNode
The problem cause
Even though ObjectMapper.treeToValue
is a Kotlin inline extension function with a reified generic parameter (which means that generics are preserved at runtime), it calls the Java ObjectMapper.treeToValue(TreeNode, Class<T>)
method. The value passed as Class<T>
will loose generic type information for generic types such as List<Comment>
, because of type erasure.
So treeToValue
can be used for:
mapper.treeToValue<Comment>(commentNode)
but not for:
mapper.treeToValue<List<Comment>>(commentsNode)
Also note that ObjectMapper
contains multiple methods that have @SuppressWarnings
annotations, which causes some problems not to appear at compile-time, but at run-time.
Solution 1 - use convertValue()
This is the best solution. It uses the Kotlin extension function ObjectMapper.convertValue
.
val commentsNode = mapper.readTree(fullJsonContent).get(0).get("Comments")val comments = mapper.convertValue<List<Comment>>(commentsNode)
Solution 2 - use an ObjectReader
This solution doesn't use jackson-module-kotlin
extension functions.
val reader = mapper.readerFor(object : TypeReference<List<Comment>>() {})val comments: List<Comment> = reader.readValue(commentsNode)
Solution 3 - deserialize in map
Because treeToValue
(Kotlin extension function) does work for non-generic types, you can first get the nodes as as list of JsonNodes, and then map each JsonNode to a Comment.
But it's cumbersome that you cannot simply return mapper.treeToValue(it)
, because that causes type inference compile errors.
val commentsNode = mapper.readTree(fullJsonContent).get(0).get("Comments")val comments = commentsNode.elements().asSequence().toList().map { val comment: Comment = mapper.treeToValue(it) comment}