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

ProGuard混淆后Jackson序列化多态类型丢失type标识信息的问题排查

ProGuard混淆后Jackson序列化多态类型丢失type标识信息的问题排查

问题概述

我在使用ProGuard(Gradle插件)混淆的项目里,用Jackson处理多态类型的序列化/反序列化时踩了个大坑:混淆后的构建中,多态类型的序列化会丢失@JsonTypeInfo指定的type属性,直接导致反序列化彻底乱套——本来应该是CarModel子类的对象,变成了LinkedHashMap,运行时直接抛出ClassCastException。

比如未混淆时的正确序列化结果:

{
  "owner" : "Jay Leno",
  "cars" : [ {
    "type" : "Corvette",
    "name" : "Corvette",
    "year" : 1963
  }, {
    "type" : "Aztek",
    "name" : "Ugly",
    "year" : 2003
  } ]
}

混淆后就变成了这样(type字段直接消失,year还被重命名成了a):

{
  "owner" : "Jay Leno",
  "cars" : [ {
    "a" : 1963,
    "name" : "Corvette"
  }, {
    "a" : 2003,
    "name" : "Ugly"
  } ]
}

问题原因分析

ProGuard在混淆过程中,会对类名、字段名进行重命名,同时如果没有正确配置规则,会破坏Jackson序列化/反序列化必需的核心信息:

  1. 关键注解被移除:@JsonTypeInfo、@JsonSubTypes这些多态标识注解可能被ProGuard误删,导致Jackson无法识别多态类型的映射规则;
  2. 类元数据丢失:多态子类的类名被混淆后,Jackson无法关联到type字段对应的具体类;
  3. 字段重命名混乱:实体类的字段(比如year)被重命名,不仅导致序列化字段名异常,还会让反序列化时无法匹配字段。

解决方案:调整ProGuard规则

要解决这个问题,咱们需要在ProGuard配置中添加针对性规则,保护Jackson多态序列化相关的类、注解和元数据:

1. 核心规则补充

添加以下规则,保留Jackson关键注解、多态类的结构及元数据:

# 保留所有注解信息,Jackson依赖注解识别序列化规则
-keepattributes *Annotation*

# 保留多态基类和子类的完整结构、字段与方法
-keep class rizzo.test.CarModel { *; }
-keep class rizzo.test.Corvette { *; }
-keep class rizzo.test.Aztek { *; }

# 保留带有多态注解的类
-keep @com.fasterxml.jackson.annotation.JsonSubTypes class *
-keep @com.fasterxml.jackson.annotation.JsonTypeInfo class *

# 保留子类的@JsonCreator构造方法,确保Jackson能正确实例化对象
-keepclassmembers class * {
    @com.fasterxml.jackson.annotation.JsonCreator <init>(...);
}

2. 修改Gradle的ProGuard任务配置

把上面的规则整合到你的proguard任务中,修改后的完整任务配置如下:

task proguard(type: proguard.gradle.ProGuardTask) {
    dependsOn classes
    
    verbose
    printmapping "${buildDir}/proguard-mapping.txt"

    injars "${buildDir}/classes/java/main"
    outjars "${buildDir}/classes/obfuscated/"

    libraryjars "${System.getProperty('java.home')}/jmods/java.base.jmod", jarfilter: '!**.jar', filter: '!module-info.class'
    libraryjars "${System.getProperty('java.home')}/jmods/java.logging.jmod", jarfilter: '!**.jar', filter: '!module-info.class'
    libraryjars "${System.getProperty('java.home')}/jmods/java.desktop.jmod", jarfilter: '!**.jar', filter: '!module-info.class'
    libraryjars "${System.getProperty('java.home')}/jmods/java.xml.jmod", jarfilter: '!**.jar', filter: '!module-info.class'
    libraryjars "${System.getProperty('java.home')}/jmods/java.sql.jmod", jarfilter: '!**.jar', filter: '!module-info.class'

    libraryjars sourceSets.main.compileClasspath

    keepdirectories

    // 新增:保护Jackson多态序列化的核心规则
    -keepattributes *Annotation*
    -keep class rizzo.test.CarModel { *; }
    -keep class rizzo.test.Corvette { *; }
    -keep class rizzo.test.Aztek { *; }
    -keep @com.fasterxml.jackson.annotation.JsonSubTypes class *
    -keep @com.fasterxml.jackson.annotation.JsonTypeInfo class *
    -keepclassmembers class * {
        @com.fasterxml.jackson.annotation.JsonCreator <init>(...);
    }

    // 原有规则:保留getter/setter和主类入口
    keepclassmembers 'class * { \
        ** get*(); \
        void set*(***); \
    }'

    keep "public class ${appMainClass} { \
            public static void main(java.lang.String[]); \
         }"

    renamesourcefileattribute 'SourceFile'
    keepattributes 'SourceFile,LineNumberTable'

    doLast {
        delete "${buildDir}/classes/java/main"
        copy {
            from "${buildDir}/classes/obfuscated/"
            into "${buildDir}/classes/java/main"
        }
        
    }
}

3. 验证效果

修改完规则后,运行./gradlew proguard jar构建混淆后的JAR,再执行java -jar build/libs/ProguardJacksonTest.jar,就能看到序列化结果和未混淆时完全一致,反序列化也不会再抛出ClassCastException了。

通用规则优化(可选)

如果你的项目中有大量多态类,可以用更通用的规则代替逐个类的配置:

# 保留所有带有@JsonTypeInfo注解的类及其子类
-keep @com.fasterxml.jackson.annotation.JsonTypeInfo class * {
    *;
}
-keep class * extends @com.fasterxml.jackson.annotation.JsonTypeInfo * {
    *;
}

这样就不用手动添加每个类名,适合类数量较多的项目。


备注:内容来源于stack exchange,提问作者E-Riz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 03:19:52