一、问题示例
实体类TestBean:
class TestBean implements Serializable{
String title;
boolean isShow = true;//这里给isShow设置了默认值,坑点
}
反序列化代码:
new Gson().fromJson("{title:\"标题\"}", TestBean.class);
预计得到的结果:
TestBean.title 值等于 “标题”
TestBean.isShow 值等于 “true”
实际得到的结果:
TestBean.title 值等于 “标题”
TestBean.isShow 值等于 “false”
二、原理分析
gson反序列化主要分为两个过程:
- 根据TypeToken创建出对象
- 根据json字符串解析数据,对对象属性赋值
对象的创建过程如下:
- 先尝试获取无参构造函数
- 失败则尝试List、Map等情况的构造函数
- 最后使用Unsafe.newInstance兜底(此兜底不会调用构造函数,导致所有对象初始化代码不会调用)
public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
final Type type = typeToken.getType();
final Class<? super T> rawType = typeToken.getRawType();
// first try an instance creator
@SuppressWarnings("unchecked") // types must agree
final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);
if (typeCreator != null) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return typeCreator.createInstance(type);
}
};
}
// Next try raw type match for instance creators
@SuppressWarnings("unchecked") // types must agree
final InstanceCreator<T> rawTypeCreator =
(InstanceCreator<T>) instanceCreators.get(rawType);
if (rawTypeCreator != null) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return rawTypeCreator.createInstance(type);
}
};
}
// 获取无参构造函数
ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);
if (defaultConstructor != null) {
return defaultConstructor;
}
// 获取List<T>,Map<T>等构造函数,对于List,Map的情况
ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType);
if (defaultImplementation != null) {
return defaultImplementation;
}
// unSafe构造出对象,不调用任何的构造函数
// finally try unsafe
return newUnsafeAllocator(type, rawType);
}
Gson反序列要工作正常,使结果符合预期的话,要求类必须有一个无参构造函数
二、解决方案
让TestBean实现一个默认构造函数:
class TestBean implements Serializable{
public TestBean() {
}
String title;
boolean isShow = true;
}
如果是内部类需要设置static才可以