Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kotlin var does not save generic type (deserialized to LinkedTreeMap instead) #1101

Closed
egor-n opened this issue Jun 12, 2017 · 11 comments
Closed

Comments

@egor-n
Copy link
Contributor

egor-n commented Jun 12, 2017

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.

@egor-n
Copy link
Contributor Author

egor-n commented Jun 13, 2017

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>.

@MaksymDovbnia
Copy link

Yes, I have same problem, but this issue reproduce only in some devices

@NightlyNexus
Copy link
Contributor

yep, you probably want @JvmSuppressWildcards.
google/dagger#668 (comment)

@egor-n
Copy link
Contributor Author

egor-n commented Jun 13, 2017

Yes, looks like annotating the List with @JvmSuppressWildcards helps:

data class BigClass(var inBig: Map<String, @JvmSuppressWildcards List<SmallClass>>? = null)

@egor-n
Copy link
Contributor Author

egor-n commented Jun 13, 2017

Seems like Gson supports wildcard types, though – see #39 and this test.

@egor-n egor-n closed this as completed Jun 13, 2017
@egor-n egor-n reopened this Jun 13, 2017
@nioncode
Copy link

Also, when using Jackson, it works just fine without an annotation.

@egor-n
Copy link
Contributor Author

egor-n commented Jun 13, 2017

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;
}

@egor-n
Copy link
Contributor Author

egor-n commented Jun 26, 2017

Closed in favor of #1107.

@egor-n egor-n closed this as completed Jun 26, 2017
@piotrek1543
Copy link

piotrek1543 commented Feb 15, 2018

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

@abbath0767
Copy link

abbath0767 commented Feb 26, 2019

as not worked so and not works, why the problem is considered solved? @egor-n

@egor-n
Copy link
Contributor Author

egor-n commented Feb 26, 2019

@abbath0767 this is a duplicate of #1107.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants