启用AGP v8.0全R8时Gson反序列化嵌套列表转LinkedTreeMap问题
AGP v8.0全R8模式下Gson反序列化嵌套对象为LinkedTreeMap的解决办法
问题场景
使用AGP v8.0并启用全R8模式时,将JSON字符串反序列化为嵌套对象,发现嵌套的List<MyAction>被Gson错误识别为LinkedTreeMap,该问题仅在minifyEnabled=true时触发。
相关代码
actions_list.json
[ { "name": "actionList1", "listA": [ { "name": "action1" }, { "name": "action2" } ] }, ... // 更多actionList项 ]
Action.kt
data class Action( @SerializedName("name") @Expose val name: String, val actions: List<MyAction>, var a: Int, ... var n: Boolean, )
MyAction.kt
data class MyActions( @SerializedName("name") val name: String, var state: MyActionState? )
MyActionState.kt
enum class MyActionState{ Nothing, Running, Done, Failed, Deactivate }
反序列化逻辑
val jsonString: String = this.assets.open("actions/actions_list.json") .bufferedReader() .use { it.readText() } val type = TypeToken.getParameterized(List::class.java,Action::class.java).type return Gson().fromJson(jsonString, type )
原ProGuard规则
-keepattributes Signature, InnerClasses, EnclosingMethod -keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations -dontwarn javax.annotation.** -dontwarn kotlin.Unit -dontwarn retrofit2.KotlinExtensions -dontwarn retrofit2.KotlinExtensions$* -dontwarn okhttp3.** -keep class okhttp3.** { *;} -dontwarn okio.** -keepattributes SourceFile,LineNumberTable -keep class com.google.gson.* -keep interface com.google.gson.* -keep class * extends com.google.gson.reflect.TypeToken -keep public class * implements java.lang.reflect.Type -keep class path.to.all.app.class -keep interface path.to.all.app.class -keep enum path.to.all.app.class -keepattributes *Annotation* -keepattributes AnnotationDefault -keepattributes Signature
问题原因
全R8模式下,默认优化会移除泛型类型的Signature信息或擦除嵌套泛型的类型参数,导致Gson无法通过反射获取List<MyAction>的实际类型,只能 fallback 到LinkedTreeMap。
解决方案
1. 修正ProGuard规则,保留嵌套泛型类型信息
在proguard-rules.pro中添加以下规则,确保Gson能识别嵌套对象的泛型类型:
# 保留实体类所在包下的所有类、字段、方法及泛型签名 -keep class path.to.your.models.** { <fields>; <methods>; } # 保留泛型相关属性,让Gson能解析嵌套泛型 -keepattributes Signature, TypeArguments, TypeParameters # 确保SerializedName注解不被移除 -keepclassmembers class * { @com.google.gson.annotations.SerializedName <fields>; }
替换
path.to.your.models为Action、MyAction、MyActionState所在的实际包路径。
2. 优化Gson实例创建(可选)
创建Gson实例时启用空值序列化,增强R8优化后的兼容性:
val gson = GsonBuilder() .serializeNulls() .create() return gson.fromJson(jsonString, type)
3. 补充注解保留规则(可选)
若实体类使用@Expose注解,补充规则确保其不被移除:
-keepclassmembers class * { @com.google.gson.annotations.Expose <fields>; }
验证步骤
- 执行
./gradlew assembleRelease重新构建Release包 - 安装包后测试反序列化逻辑
- 检查嵌套对象类型是否正确为
MyAction实例,而非LinkedTreeMap
内容的提问来源于stack exchange,提问作者Farhad7
相关产品推荐
相关产品推荐

