为什么呢?
- 因为反序列化创建对象本质还是利用反射, 会根据 json 字符串的 key 作为属性名称, value 则对应属性值.
如何解决
-
将序列化和反序列化的类排除混淆
-
使用 @SerializedName 注解字段
@SerializedName(parameter) 通过注解属性实现了
-
序列化的结果中, 指定该属性 key 为 parameter 的值.
-
反序列化生成的对象中, 用来匹配 key 与 parameter 并赋予属性值.
一个简单的用法为
public class Item {
@SerializedName(“name”)
public String name;
@SerializedName(“id”)
public int id;
}
当然也可以直接这么写
public class Item implements Serializable{
public String name;
public int id;
}
上面是通过添加 @SerializedName 注解实现混淆之后反序列化出现的问题,下面我们说下将将序列化和反序列化的类排除混淆该怎么做。
package com.baidu.bean;
public class Item {
public String name;
public int id;
public static class PageConfig {
public String type;
}
}
Item 中增加了一个内部类 PageConfig。
这里敲黑板了:
1.Item 里面的字段、Item 里面引用到的类和 Item 里面的内部类 PageConfig 都需要实现序列化 (implements Serializable);
- 如果不是 implements Serializable 实现序列化,而是给每个字段加上 @SerializedName 注解,那么务必注意:Item 里面的字段、Item 里面引用到的类的和 Item 里面的内部类的字段都需要加上 @SerializedName 注解,否则会出现莫名其妙的问题:不会崩溃,就是各种奇怪现象,而在 debug 下又不出现这个问题。
最常见的做法是:
-keep class com.baidu.bean.** { *; }
含义是:将 bean 目录下包括子目录下的类排除不被混淆
单独排除某个类可以这么写:
-keep class com.baidu.bean {*;}
单独排除某个类的内部类需要这么写:
-keep class class com.baidu.bean.Item$PageConfig {*;}
如果很多实体类里面有内部类,建议组合起来写:
-keep class com.baidu.bean.**{ *;}
-keep class com.baidu.bean.**$*{ *;}
另外,下面的写法也是可以的,主要以上面的写法为主。具体要使用哪种,读者可以自己根据需要使用。
-keep class com.baidu.bean.$** { ;}
-keep class com.baidu.bean.$ {*;}
-keep class com.baidu.bean.**$* {*;}
上面出现了 * 和 ** 通配符的配置,为了便于加深印象,这里延伸阅读下:
============================================================================
1. 混淆配置
android{
buildTypes {
release {
buildConfigField “boolean”, “LOG_DEBUG”, “false” //不显示log
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
signingConfig signingConfigs.config
}
}
}
因为开启混淆会使编译时间变长,所以 debug 模式下不开启。我们需要做的是:
-
将
release下minifyEnabled
的值改为true
,打开混淆; -
加上
shrinkResources true
,打开资源压缩。
3.buildConfigField
不显示 log 日志
4.sig