kolay
kolay

Reputation: 73

Why kotlin jackson can't deserialize list

I have a function:

inline fun <reified T : Any>parse(result: String): T  = mapper.readValue<Response<T>>(result).someValue

When I pass a list type, e.g. List<MyClass>, and try to get some item from it, I get the following exception:

Exception in thread "ForkJoinPool.commonPool-worker-3" 
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to MyClass

Upvotes: 7

Views: 3211

Answers (1)

Roland
Roland

Reputation: 23262

You need to pass the type to the readValue-function, otherwise Jackson has no way to know to which type it should transform to. By default jackson then just returns a map with keys and its values.

So for your particular problem you may just make the parse-function inline and add a reified to your passed type. This ensures, that the actual type is also passed to Jackson. See also reified types in the kotlin reference. Alternatively you pass the actual type (either using TypeReference or the class itself if it's not generic).

Previously this answer also contained a general information how to deserialize a json list to an actual one, which I will leave here for reference:

mapper.readValue(result, object : TypeReference<List<MyClass>>() {})

or if you use jackson-module-kotlin:

mapper.readValue<List<MyClass>>(result)

Applied to your function that could look like the following:

inline fun <reified T : Any>parse(result: String): T  = mapper.readValue(result, object : TypeReference<T>() {})

or using jackson-module-kotlin:

inline fun <reified T : Any>parse(result: String): T  = mapper.readValue(result)

Calling it would then just be:

val yourObjList = parse<List<MyClass>>(yourJson)
// or
val yourObjList : List<MyClass> = parse(yourJson)

Note that I used reified (which implies inline). If you do not use reified the actual type is not passed on to jackson-module-kotlin's reified methods.

Upvotes: 5

Related Questions