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

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

验证步骤

  1. 执行./gradlew assembleRelease重新构建Release包
  2. 安装包后测试反序列化逻辑
  3. 检查嵌套对象类型是否正确为MyAction实例,而非LinkedTreeMap

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:43:15