Problem
I have JSON content in the form of a string, which I first want to traverse programmatically with Jackson. Then, when I have the node of interest, I want to deserialize it.
What I have tried
I have successfully deserialized strings using mapper.readValue, but now I want to perform such an operation on a jsonNode instead of a string.
Libraries
- jackson-core:2.9.9
- jackson-module-kotlin:2.9.9
- Kotlin 1.3.41
- kotlin-stdlib-jdk8:1.3.41
Code
package somepackage
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule
import com.fasterxml.jackson.module.kotlin.readValue
import com.fasterxml.jackson.module.kotlin.treeToValue
fun main() {
val mapper = ObjectMapper().registerModule(KotlinModule())
readValueWorksFine(mapper)
treeToValueFails(mapper)
}
fun treeToValueFails(mapper: ObjectMapper) {
val fullJsonContent = """
[{
"product_id":123,
"Comments":
[{
"comment_id": 23,
"message": "Hello World!"
}]
}]
""".trimIndent()
// Traverse to get the node of interest
val commentsNode: JsonNode = mapper.readTree(fullJsonContent).get(0).get("Comments")
// Deserialize
val comments: List<Comment> = mapper.treeToValue<List<Comment>>(commentsNode)
// The line below fails. (I would have expected the exception to be thrown in the line above instead.
// Exception:
// Exception in thread "main" java.lang.ClassCastException: class
// java.util.LinkedHashMap cannot be cast to class somepackage.Comment (java.util.LinkedHashMap is in module
// java.base of loader 'bootstrap'; somepackage.Comment is in unnamed module of loader 'app')
for (comment: Comment in comments) { // This line fails
println(comment.comment_id)
println(comment.message)
}
}
fun readValueWorksFine(mapper: ObjectMapper) {
val commentsJsonContent = """
[{
"comment_id": 23,
"message": "Hello World!"
}]
""".trimIndent()
val comments1: List<Comment> = mapper.readValue<List<Comment>>(commentsJsonContent)
for (comment in comments1) {
println(comment)
}
}
data class Comment(val comment_id: Long, val message: String)
Exception/Output
The code above results in the following exception/output:
Comment(comment_id=23, message=Hello World!)
Exception in thread "main" java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class somepackage.Comment (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; somepackage.Comment is in unnamed module of loader 'app')
at somepackage.TKt.treeToValueFails(T.kt:39)
at somepackage.TKt.main(T.kt:13)
at somepackage.TKt.main(T.kt)