You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复SharedPreferences中Gson解析ProGuard混淆后的变量名错乱问题

解决Gson解析混淆旧数据的问题

核心原因

之前开启ProGuard时未保护WaterModel的字段,导致序列化到SharedPreferences的JSON用了混淆后的a/b/c/d作为键;现在加了keep规则后,Gson解析时会用原始字段名id/date/waterMl/waterPercent匹配,自然对应不上,抛出解析异常。

解决方案

1. 给POJO字段添加多别名兼容

用Gson的@SerializedName注解,给每个字段同时标注原始名称和混淆后的别名,让Gson能识别两种键名:

import com.google.gson.annotations.SerializedName;

public class WaterModel {
    @SerializedName(value = "id", alternate = {"a"})
    private int id;
    
    @SerializedName(value = "date", alternate = {"b"})
    private String date;
    
    @SerializedName(value = "waterMl", alternate = {"c"})
    private int waterMl;
    
    @SerializedName(value = "waterPercent", alternate = {"d"})
    private float waterPercent;

    // 保留原有的getter/setter方法
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public String getDate() { return date; }
    public void setDate(String date) { this.date = date; }
    public int getWaterMl() { return waterMl; }
    public void setWaterMl(int waterMl) { this.waterMl = waterMl; }
    public float getWaterPercent() { return waterPercent; }
    public void setWaterPercent(float waterPercent) { this.waterPercent = waterPercent; }
}

这样Gson解析时,不管JSON里是a还是id,都会映射到id字段,旧数据就能正常解析了。

2. 迁移旧数据到未混淆格式

解析成功后,把数据重新用未混淆的字段名序列化,存回SharedPreferences,避免后续一直兼容旧格式:

Gson gson = new Gson();
String oldJson = sharedPreferences.getString(WATER_LIST, null);
Type type = new TypeToken<List<WaterModel>>() {}.getType();
List<WaterModel> modelList = gson.fromJson(oldJson, type);

// 重新序列化未混淆的JSON
String newJson = gson.toJson(modelList);
// 存回SharedPreferences
sharedPreferences.edit().putString(WATER_LIST, newJson).apply();

执行一次后,SP里的JSON就会变成{"id":1, "date":"20/07/2022"...}这种格式,后续就不需要再兼容旧别名了(后续版本可以去掉alternate参数)。

3. 确认ProGuard规则生效

确保你的ProGuard规则已经正确保护了WaterModel,避免后续再出现字段混淆:

  • 方法一:在ProGuard配置文件中添加规则:
-keep class com.your.package.name.WaterModel { *; }
  • 方法二:直接在WaterModel类上添加@Keep注解(需导入androidx.annotation.Keep或android.support.annotation.Keep):
import androidx.annotation.Keep;

@Keep
public class WaterModel {
    // ...字段和方法
}

额外注意

如果后续还有其他POJO类需要序列化,一定要提前配置ProGuard保护,或者用@Keep/@SerializedName固定字段名,避免再次出现类似问题。

内容的提问来源于stack exchange,提问作者user18504539

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 00:48:20