Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 428
Iain STIRZAKER Avatar asked Oct 04 '22 12:10

Iain STIRZAKER


2 Answers

Add the following to your Proguard.config. It will help you locate the issue.

-verbose 
-dump class_files.txt 
-printseeds seeds.txt 
-printusage unused.txt 
-printmapping mapping.txt

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

I believe you should be using proguard-android-optimize.txt, and not proguard-android.txt.

For completeness, thank Riley Hassell on Android Security Discussions for the tricks.

like image 98
jww Avatar answered Oct 10 '22 02:10

jww


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.

like image 20
Eric Lafortune Avatar answered Oct 10 '22 01:10

Eric Lafortune