Gson deserializa puntero nulo en apk liberado

Estoy escribiendo una aplicación para Android que necesito usar gson para deserializar la cadena json:

{ "reply_code": 001, "userinfo": { "username": "002", "userip": 003 } } 

Así que creo dos clases:

 public class ReturnData { public String reply_code; public userinfo userinfo; } public class userinfo { public String username; public String userip; } 

Finalmente, mi código Java en MainActivity.java:

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Context context= MainActivity.this; //Test JSON String JSON="{\"reply_code\": 001,\"userinfo\": {\"username\": \"002\",\"userip\": 003}}"; Gson gson = new Gson(); ReturnData returnData=gson.fromJson(JSON,ReturnData.class); if(returnData.reply_code==null) Toast.makeText(context,"isNULL",Toast.LENGTH_SHORT).show(); else Toast.makeText(context,"notNULL",Toast.LENGTH_SHORT).show(); } 

Lo que me hizo confundir es, cuando depuro la aplicación, se ejecutó bien y la salida "notNULL". Puedo ver cada atribución del objeto ha sido deserialized correctamente. Sin embargo, cuando he generado apk liberado de Android Studio y ejecutar apk en el teléfono, la salida "isNULL", la resolución json falló!

¿Quién puede decirme qué sucedió?

PS: build.gradle:

 apply plugin: 'com.android.application' android { compileSdkVersion 19 buildToolsVersion "19.1" defaultConfig { applicationId "com.padeoe.autoconnect" minSdkVersion 14 targetSdkVersion 21 versionCode 1 versionName "2.1.4" } buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') compile files('src/gson-2.3.1.jar') } 

Tiene ProGuard habilitado en su tipo de versión de release : minifyEnabled true . Obfusca el código cambiando los nombres de clase / variable.

Debería anotar las propiedades de su clase, por lo que Gson sabe qué buscar:

 public class ReturnData { @SerializedName("reply_code") public String reply_code; @SerializedName("userinfo") public userinfo userinfo; } public class userinfo { @SerializedName("username") public String username; @SerializedName("userip") public String userip; } 

De esta manera Gson no mirará los nombres de las propiedades, sino que mirará la anotación @SerializedName .

Puede utilizar @SerializedName como se menciona por @Egor N o puede agregar las clases de Gson a proguard-rules.pro mediante

 -keep class com.packageName.yourGsonClassName 

Este último tiene las siguientes ventajas sobre el primero:

  • Al escribir su código puede poner toda su clase de Gson en una carpeta y mantener todos ellos de ofuscación con lo siguiente, lo que ahorra una gran cantidad de codificación:

     -keep class com.packageName.gsonFolder.** { *; } 
  • La adición de @SerializedName a cada campo en las clases de Gson no sólo requiere mucho tiempo, especialmente en grandes proyectos con muchos archivos Gson, sino que también aumenta la posibilidad de errores al introducir el código, si el argumento en el @SerializedName es diferente del nombre del campo.

  • Si se utilizan otros métodos, como los métodos getter o setter en la clase Gson, también pueden obfuscated. No utilizar @SerializedName para estos métodos provoca fallo en tiempo de ejecución debido a conflicto en nombres.

Cambie su código json a lo siguiente ..

 { "reply_code": "001", "userinfo": [ { "username": "002" }, { "userip": "003" } ] } 

Ahora trate de analizar el json …

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.