data class BigClass(var inBig: Map<String, List<SmallClass>>? = null)
data class SmallClass(var inSmall: String? = null)
fun main(args: Array<String>) {
val json = """
{
"inBig": {
"key": [
{ "inSmall": "hello" }
]
}
}
"""
val deserialized = Gson().fromJson(json, BigClass::class.java)
println(deserialized.inBig!!["key"]!![0].inSmall) // should print "hello" but throws instead
}
Executing the code above will lead to the following Exception:
Exception in thread "main" java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to SmallClass
at MyClass.main(MyClass.kt:18)
The List<SmallClass> is actually deserialized to List<LinkedTreeMap>.
However, if I changed the definition of inBig variable to be a constant, then it deserializes just fine:
data class BigClass(val inBig: Map<String, List<SmallClass>>? = null)
I changed var to val and the code prints "hello" as expected.
Kotlin 1.1.1 and Gson 2.8.1.
I have run javap on both cases and here are the results:
// `BigClass` with `val inBig` is compiled to
public final class BigClass {
private final java.util.Map<java.lang.String, java.util.List<SmallClass>> inBig;
public final java.util.Map<java.lang.String, java.util.List<SmallClass>> getInBig();
// ...
}
// `BigClass` with `var inBig` is compiled to
public final class BigClass {
private java.util.Map<java.lang.String, ? extends java.util.List<SmallClass>> inBig;
public final java.util.Map<java.lang.String, java.util.List<SmallClass>> getInBig();
// ...
}
The var case adds ? extends in front of the java.util.List<SmallClass>.
Yes, I have same problem, but this issue reproduce only in some devices
yep, you probably want @JvmSuppressWildcards.
https://github.com/google/dagger/issues/668#issuecomment-289713497
Yes, looks like annotating the List with @JvmSuppressWildcards helps:
data class BigClass(var inBig: Map<String, @JvmSuppressWildcards List<SmallClass>>? = null)
Seems like Gson supports wildcard types, though – see #39 and this test.
Also, when using Jackson, it works just fine without an annotation.
I have done some more research and it seems like Kotlin is not at fault. Gson fails with the same exception for the following Java class (which is similar to the Kotlin one in the issue description):
class BigClass {
Map<String, ? extends List<SmallClass>> inBig;
}
// ...
class SmallClass {
String inSmall;
}
Closed in favor of #1107.
after adding in data class @JvmSuppressWildcards(suppress = true) to problematic field I still get LinkedTreeMap
@JvmSuppressWildcards(suppress = true)
@SerializedName("patient")
@Expose
var patient: Any? = null
as not worked so and not works, why the problem is considered solved? @egor-n
@abbath0767 this is a duplicate of #1107.
Most helpful comment
after adding in data class
@JvmSuppressWildcards(suppress = true)to problematic field I still getLinkedTreeMap