Gson反序列化时导致实体类的默认值失效了

一、问题示例

实体类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才可以

猜你喜欢

转载自blog.csdn.net/weixin_42600398/article/details/123034387