开启 Proguard 的情况下使用 GSON 出现空指针异常的处理

在使用 GSON 处理 JSON 的时候,如果项目开启了 Proguard 对代码进行压缩和混淆的话,有一些注意事项需要留意一下,否则可能出现 NullPointerException 进而导致 App Crash。

出现 NullPointerException 的原因主要是代码经过 Proguard 混淆了之后,类内部的成员变量名称发生了变化。这时候 GSON 无法找到 JSON 字段中对应的类成员变量,进而导致在使用 GSON 解析 JSON 的时候生成的对象内部的成员都是 null,之后再调用相应对象的成员的时候就可能会出现 NullPointerException。

这个问题的解决办法也十分简单,主要有两种处理方式:

解决方法

使用 @SerializedName 注解

对需要被 GSON 使用到的实体类的成员使用 @SerializedName 注解,如下所示:

1
2
3
4
5
6
public class User {
@SerializedName("username")
public String username;
@SerializedName("password")
public String password;
}

这样一来,就算代码被 Proguard 混淆之后,GSON 也能通过 @SerializedName 注解找到对应的类成员。

修改 Proguard 规则,不对实体类进行混淆

主要是修改 proguard-rules.pro 文件,不对需要序列化或者是反序列化的类进行混淆。

以下是 GSON 官方示例提供的 Proguard 规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
##---------------Begin: proguard configuration for Gson  ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }

# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { <fields>; }

# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

# Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * {
@com.google.gson.annotations.SerializedName <fields>;
}

##---------------End: proguard configuration for Gson ----------

其实就是修改 Proguard 规则,不对需要被 GSON 使用到的实体类进行混淆,核心语句主要是:

1
-keep class com.packageName.yourGsonClassName
Buy me a cup of coffee