kotlin gson反序列化默认值失效深入讲解
程序员文章站
2022-07-04 09:53:24
gson反序列化原理
原理简述
gson反序列化主要分为两个过程:
根据typetoken创建出对象
根据json字符串解析数据,对对象属性赋值...
gson反序列化原理
原理简述
gson反序列化主要分为两个过程:
- 根据typetoken创建出对象
- 根据json字符串解析数据,对对象属性赋值
对象的创建
constructorconstructor.get
- 先尝试获取无参构造函数
- 失败则尝试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); }
constructorconstructor.newdefaultconstructor
- 调用class.getdeclaredconstructor获取无参构造函数
private <t> objectconstructor<t> newdefaultconstructor(class<? super t> rawtype) { try { // 获取无参构造函数 final constructor<? super t> constructor = rawtype.getdeclaredconstructor(); if (!constructor.isaccessible()) { accessor.makeaccessible(constructor); }
constructorconstructor.newunsafeallocator
- 调用unsafe.newinstance创建出对象
- 不会调用构造函数,因此所有的初始化的代码都不会被调用
private <t> objectconstructor<t> newunsafeallocator( final type type, final class<? super t> rawtype) { return new objectconstructor<t>() { private final unsafeallocator unsafeallocator = unsafeallocator.create(); @suppresswarnings("unchecked") @override public t construct() { try { // object newinstance = unsafeallocator.newinstance(rawtype); return (t) newinstance; } catch (exception e) { throw new runtimeexception(("unable to invoke no-args constructor for " + type + ". " + "registering an instancecreator with gson for this type may fix this problem."), e); } } }; }
结论
- gson反序列要工作正常,使结果符合预期的话,要求类必须有一个无参构造函数
kotlin构造函数默认参数和无参构造函数的关系
参数里面存在没有默认值的情况
kotlin代码
- id没有默认值
class user(val id: int, val name: string = "sss") { init { println("init") } }
反编译的java代码
- 包含两个构造函数,一个是我们声明的全参数构造函数,另一个是kotlin生成的辅助构造函数
- 不包含无参构造函数
public final class user { private final int id; @notnull private final string name; public user(int id, @notnull string name) { intrinsics.checkparameterisnotnull(name, "name"); super(); this.id = id; this.name = name; string var3 = "init"; system.out.println(var3); } // $ff: synthetic method public user(int var1, string var2, int var3, defaultconstructormarker var4) { if ((var3 & 2) != 0) { var2 = ""; } this(var1, var2); } }
gson反序列化输出
代码:
@test fun testjson() { val user = gson().fromjson("{}", user::class.java) print(user.name) }
输出:不符合预期(我们声明的非空的name实际结果是null)
null
process finished with exit code 0
参数都包含默认参数的情况
kotlin代码
class user(val id: int=1, val name: string = "sss") { init { println("init") } }
反编译java代码
- 除了上面的两个构造函数,多了一个无参构造函数(从逻辑上讲,这个也符合预期)
public final class user { private final int id; @notnull private final string name; public user(int id, @notnull string name) { intrinsics.checkparameterisnotnull(name, "name"); super(); this.id = id; this.name = name; string var3 = "init"; system.out.println(var3); } // $ff: synthetic method public user(int var1, string var2, int var3, defaultconstructormarker var4) { if ((var3 & 1) != 0) { var1 = 1; } if ((var3 & 2) != 0) { var2 = ""; } this(var1, var2); } // 无参构造函数 public user() { this(0, (string)null, 3, (defaultconstructormarker)null); } }
gson反序列化输出
代码:
@test fun testjson() { val user = gson().fromjson("{}", user::class.java) print(user.name) }
输出:符合预期
init
sss
process finished with exit code 0
best practice
practice1
- 属性声明在构造函数,所有参数都带默认值
- 不确定的参数声明为可空
class user(val id: int=1 , val name: string = "sss") { init { println("init") } }
practice2
回归到java的写法即可
class user { val id: int = 1 val name: string = "sss" init { println("init") } }
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。