Search code examples
javaandroidgsonkotlinproguard

ProGuard makes Gson return LinkedTreeMap instead of my type


The following line of code works for me normally:

val users: Array<Catalog> = com.google.gson.Gson().fromJson(data, Array<MyUserClass>::class.java)

But when I enable ProGuard, I get this error:

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.app.Models.MyModel

MyUserClass is as follows:

data class MyUserClass(var posts: List<UserPosts>)

So Gson properly makes users be MyUserClass - but instead of MyUserClass being a list of UserPosts, it ends up being a list of LinkedTreeMap

I've been trying to solve this for a while now, and all the answers I found related to this have to do with generics, but I'm not using generics, I'm passing the class directly to Gson.

I'm completely lost at this point, so any guidance would be apprecciated

Here's the related ProGuard rules:

##---------------Begin: proguard configuration for Gson  ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }

# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }

-keep class com.example.Models.** { *; }

# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
##---------------End: proguard configuration for Gson  ----------

-keep public class MyUserClass
-keep public class UserPosts

Solution

  • Make sure your proguard.cfg contains all of the rules:

        ##---------------Begin: proguard configuration for Gson  ----------
    # Gson uses generic type information stored in a class file when working with fields. Proguard
    # removes such information by default, so configure it to keep all of it.
    -keepattributes Signature
    
    # For using GSON @Expose annotation
    -keepattributes *Annotation*
    
    # Gson specific classes
    -keep class sun.misc.Unsafe { *; }
    #-keep class com.google.gson.stream.** { *; }
    
    # Application classes that will be serialized/deserialized over Gson
    -keep class com.google.gson.examples.android.model.** { *; }
    
    # Prevent proguard from stripping interface information from TypeAdapterFactory,
    # JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
    -keep class * implements com.google.gson.TypeAdapterFactory
    -keep class * implements com.google.gson.JsonSerializer
    -keep class * implements com.google.gson.JsonDeserializer
    
    ##---------------End: proguard configuration for Gson  ----------
    -keep public class MyUserClass
    -keep public class UserPosts