Gson deserialize null pointer in released apk

与世无争的帅哥 提交于 2019-11-29 00:53:58

问题


I'm writing an Android app need using gson to deserialize the json string:

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

so I create two classes:

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

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

finally, my Java code in 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();
}

What made me confused is, when I debug the app,it ran well and output "notNULL".I can see the every attribution of the object has been deserialized properly. However,when I generated released apk from Android Studio and run apk on phone,it output "isNULL",the json resolution failed!

Who can tell me what happened?!

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')
}

回答1:


You have ProGuard enabled in your release build type - minifyEnabled true. It obfuscates the code by changing class/variable names.

You should annotate your class properties, so Gson knows what to look for:

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;
}

This way Gson won't look at the properties' names, but will look at @SerializedName annotation.




回答2:


You can either use @SerializedName as mentioned by @Egor N or you may add the Gson classes to the proguard-rules.pro by using

-keep class com.packageName.yourGsonClassName

The latter has the following advantages over the former:

  • when writing your code you can put all your Gson class in a folder and keep all of them from obfuscation using the following, which saves a lot of coding:

    -keep class com.packageName.gsonFolder.** { *; }
    
  • Adding @SerializedName to each field in Gson classes is not only time-consuming especially in large projects with lots of Gson files but also increases the possibility of mistakes entering the code, if the argument in the @SerializedName is different from the field name.

  • If any other methods, such as getter or setter methods are used in the Gson class, they may also get obfuscated. Not using @SerializedName for these methods causes crash in runtime due to conflict in names.



来源:https://stackoverflow.com/questions/30001674/gson-deserialize-null-pointer-in-released-apk

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!