Solution to the problem of field being optimized when using GSON serialized object in android


1. Problem description

Has the following structure:

public class NativeParam<T> {

    private T data;

    public NativeParam(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
};

NativeParam<String> data = "1.0.1";
String result = gson.toJson(new NativeParam<>("1.0.1"));
log.i(TAG,"GET_APP_VERSION_INFO-result:" + result);
});

The output information is as follows:

GET_APP_VERSION_INFO-result:{"a":"1.0.1"}

As shown above, the "data" field is serialized into "a".


2. Problem solving process and cause analysis


At first I thought that the fields were optimized into "a", "b", etc. This may be because the Gson library enables the field obfuscation (Field Naming Policy) function by default to compress the field names into a shorter form.


Try the following two methods to resolve:


1. Disable field obfuscation

Disable field obfuscation by setting Gson's field naming policy. You can use GsonBuilderthe class to create a Gson object and call setFieldNamingPolicythe method to set the field naming strategy. Here is sample code to disable field obfuscation:

Gson gson = new GsonBuilder()
        .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
        .create();

String jsonString = gson.toJson(yourObject);

By using FieldNamingPolicy.IDENTITYas the field naming strategy, the field names will remain consistent with the field names in the original object and will not be compressed.


2. Use @SerializedNameannotations

If you want to disable field obfuscation only for specific fields, you can use an annotation on those fields @SerializedNameand specify the original field name for the annotation's value.


as follows:

class YourClass {
    @SerializedName("originalFieldName")
    private String fieldName;
    // ...
}

Gson gson = new Gson();
String jsonString = gson.toJson(yourObject);

By using the annotation on a field @SerializedName, you can specify the original field name that the field should use when serialized to a JSON string, without being affected by field obfuscation.


However, the above two methods failed to solve the problem.

Suddenly I thought that being optimized into "a" and "b" was a bit like turning on code obfuscation during packaging, so I decisively added gson's obfuscation rules, and the problem was solved.


3. Final solution

In addition to gson's obfuscation rules, note: com.test.demo.NativeParam needs to be replaced with your own mode structure.


#gson  start
# custom 不能混淆的要加上
# Application classes that will be serialized/deserialized over Gson
-keep class com.test.demo.NativeParam {  *; }

#gson start
-keep class com.google.gson.** {*;}
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.reflect.TypeToken { *; }
-keep class * extends com.google.gson.reflect.TypeToken
-keep class com.google.** {
    <fields>;
    <methods>;
}
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}
-dontwarn com.google.gson.**
#gson  end

The test output results are as follows:

GET_APP_VERSION_INFO-result:{"data":"1.0.1"}

Guess you like

Origin blog.csdn.net/lizhong2008/article/details/135140711