Search code examples
androidproguardrestlet

ProGuard - org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type


I have an Android-based application which is connecting to the Google App Engine using Rest services, the app works perfectly until it is obfuscated through ProGuard prior to release.

The error reported in LogCat when running the obfuscated app is:

Unable to convert a [application/json,UTF-8] representation into an object of 
  class com.enterprisemk.android.bcw.bincollection.WasteCollectionAreasContainer

org.codehaus.jackson.map.JsonMappingException: No suitable constructor found 
  for type [simple type, class 
  com.enterprisemk.android.bcw.bincollection.WasteCollectionAreasContainer]: 
  can not instantiate from JSON object (need to add/enable type information?)

I have the following in my proguard-project.txt file:

-keepattributes *Annotation*,EnclosingMethod

-keep public class org.w3c.** {public private protected *;}
-dontwarn org.w3c.**

-keep public class org.joda.time.** {public private protected *;}
-dontwarn org.joda.time.**

-keep public class org.restlet.** { *; }
-dontwarn org.restlet.**

-keep public class org.codehaus.** { *; }
-dontwarn org.codehaus.**

-keepattributes Signature
-keepnames class com.fasterxml.jackson.** { *; }
-dontwarn com.fasterxml.jackson.databind.**

And my class the error refers to looks like:

public class WasteCollectionAreasContainer {

 public List<WasteCollectionAreas> wasteCollectionAreasList;

 public List<WasteCollectionAreas> getWasteCollectionAreasList() {
     return wasteCollectionAreasList;
 }

 public void setWasteCollectionAreasist(List<WasteCollectionAreas> wasteCollectionAreasList) {
     this.wasteCollectionAreasList = wasteCollectionAreasList;
 }

 public WasteCollectionAreasContainer() {
     wasteCollectionAreasList = new ArrayList<WasteCollectionAreas>();
 }

 @JsonCreator
 public WasteCollectionAreasContainer(List<WasteCollectionAreas> wasteCollectionAreasList) {
     this.wasteCollectionAreasList = wasteCollectionAreasList;
 }
}

To reiterate prior to obfuscation through ProGuard the app works perfectly.
Can anyone help me solve this problem?


Solution

  • The error message

    org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type
        [simple type, class com.enterprisemk.android.bcw.bincollection.WasteCollectionAreasContainer]:
        can not instantiate from JSON object (need to add/enable type information?)
    

    suggests that the Jackson library is trying to deserialize your class using reflection, with its original name and its annotated constructor. ProGuard can't foresee this, so it may have removed or renamed the class and its constructor. You probably need to preserve them explicitly:

    -keep class com.enterprisemk.android.bcw.bincollection.WasteCollectionAreasContainer {
        <init>(java.util.List);
    }
    

    There may be other similar classes/fields/methods that need to be preserved for the same reasons.