Android调试版REST调用传参正常 签名APK中POST请求pass字段为null
问题根本原因
这个现象和POST请求本身的业务逻辑完全无关,是Android Release签名构建默认开启的R8/ProGuard代码压缩混淆机制导致的。
- 调试构建默认关闭代码压缩,所有类、字段、方法都保留原始定义,Retrofit通过反射序列化User对象时,能正确读取到
name和pass字段,生成符合服务端要求的JSON请求体。 - Release签名构建默认开启代码压缩,R8会通过静态字节码扫描判定无用代码,对没有被“直接代码调用”的类、方法、字段执行移除或重命名操作。R8无法识别反射调用逻辑(Retrofit的序列化过程完全基于反射实现)。
- 为什么只有
pass字段丢失?对照你定义的User类逻辑就能发现:name字段在多个构造函数、本地用户信息读取、登录态展示等业务逻辑里被直接读写,R8判定它为有效代码,不会修改它的字段名。pass字段仅在双参/三参构造函数里被赋值,你的客户端业务代码全程没有直接调用getPass()或读取pass字段的逻辑,R8判定这个字段、对应的getter/setter都是无用代码,直接从类结构中移除或重命名。最终序列化生成的JSON里根本没有pass键,服务端接收到的自然就是null。
修复方案
在app模块的proguard-rules.pro混淆规则文件中添加白名单,阻止R8修改需要被网络序列化的实体类:
- 针对当前的User类,直接添加规则:
-keep class com.你的应用包名.User { *; }
这条规则会让R8保留这个类的所有结构、方法、字段,不做任何修改。 - 如果使用Gson作为Retrofit的JSON转换器,可以补充通用的Gson混淆规则,避免后续新增实体类再出现同类问题:
# 保留Gson核心类 -keep class com.google.gson.** { *; } # 保留类上的注解信息,支持@SerializedName等注解 -keepattributes *Annotation* # 保留所有实体类的字段定义 -keep class com.你的应用包名.model.** { <fields>; }
修改完成后重新生成Release签名包,序列化行为就会和调试版本完全一致。
内容的提问来源于stack exchange,提问作者user21597761
相关产品推荐
相关产品推荐

