AssertionError in Gson EnumTypeAdapter when using Proguard Obfuscation

It seems like we must request that enumerations' members are kept. Adding this to the proguard config file worked for me:

-keepclassmembers enum * { *; }

Or, if you want to be more specific,

-keepclassmembers enum com.your.package.** { *; }

GSON throws this AssertionError when it fails to deserialize enumeration constants from JSON data, performing introspection on the fields of the enum class. Unfortunately, it swallows the details of the underlying NoSuchFieldException.

You should make sure that you preserve the names of the enum fields (and of fields in general) that are serialized. By default, ProGuard may rename or even remove them. For instance, with some wildcards:

-keepclassmembers class com.example.domain.** {
    <fields>;
}

It is already suggested that you need to configure Proguard in a way that it keeps every enum related to serialized objects intact. I don't really like the fact that I have to explicitly list all my enums, this solution is hard to maintain. A slightly better solution I came up with is the following.

Use an empty interface to indicate that a class or enum takes part in Gson serialization:

public interface GsonSerializable { }

public class MyClass implements GsonSerializable {

    public enum MyEnum implements GsonSerializable {
        enumvalue1, enumvalue2
    }

    public MyEnum mydata1;
}

Use a Proguard config that keeps both the interface and all classes/enums that implement it:

# keep GsonSerializable interface, it would be thrown away by proguard since it is empty
-keep class com.example.GsonSerializable

# member fields of serialized classes, including enums that implement this interface
-keepclassmembers class * implements com.example.GsonSerializable {
    <fields>;
}

# also keep names of these classes. not required, but just in case.
-keepnames class * implements com.example.GsonSerializable

That's it, as long as your classes and enums use the interface, you should be OK. You could also enforce the presence of this interface in your serialization/deserialization methods, so you don't forget it when adding a new class later:

public String serializeWithGson(GsonSerializable object) { ... }

Also in your configuration the line with 'com.google.gson.examples.android.model.** { *; }' refers to some Google related example code, so I don't think it is necessary.


In my case, proguard was configured to -keep individual classes touched by Gson, but the error went away when I configured proguard to retain the package where those individual classes resided:

-keep class com.company.library.model.** { *; }