作者:Viata
链接:https://juejin.cn/post/6913512989916135432
在相当长的一段时间里,kotlin一直都没有自己专属的序列化/反序列化库。于是只能拿Java的库来将就一下,最常用的大概就是Gson了。但是这样一来Kt的很多强大特性就用不了,比如参数默认值,属性委托等,就这样被迫退化为Javaer了(没错,在下正是kotlin吹,Java叛徒)。 虽然社区也维护了支持Kt特性的第三方序列化库,比如moshi,but并不好用,Gson用习惯了就喜欢这种简洁直白的女孩子(bushi)。想了解Moshi的自己去查吧,个人认为官方库出来后Moshi离完蛋不远了。
Gson 在开始介绍今天的主角之前,先来回顾一下Gson在kt中的用法,与Java没啥区别:
//使用数据类的原因是对象可以直接打印出来
data class Student(val name: String, val score: Int = 80)
fun main(){
val gosn = Gson()
val Icarus = Student("Icarus", 99)
println(gson.toJson(Icarus))//{"name":"Icarus","score":99}
val Icarus2 = gson.fromJson("""{"name":"Icarus","score":99}""", Student::class.java)
println(Icarus2)//Student(name=Icarus, score=99)
println(Icarus == Icarus2)//true
//下面是参数有缺省值的情况
val SoharaMitsuki = Student("SoharaMitsuki")
println(gson.toJson(SoharaMitsuki ))//{"name":"SoharaMitsuki","score":80}
val SoharaMitsuki2 = gson.fromJson("""{"name":"SoharaMitsuki"}""", Student::class.java)
println(SoharaMitsuki2)//{"name":"SoharaMitsuki2","score":0}
}
注意到,我们定义的score属性有默认值,我就直接说结论了,使用默认值生成的对象序列化成Json字符串一切正常,但是Gson使用未给出属性值的Json字符串反序列化为Student对象,score属性值是0,不会用到默认值的,因为Gson会先去类定义里面找对应的构造函数,就是参数列表不带这个属性的构造函数,没找到就会用到Java黑魔法Unsafe类,直接创建对象。 data class Student WithInits(val name: String, val score: Int){
val firstName by lazy {
name.split(" ")[0]
}
/**
*用by lazy跟随的属性没有幕后字段,初始化时不会再内存中给它开一个存储值的空间
*初次使用该属性时才会lazy后面的代码,把引用指向代码返回的那块内存
*专业名称是延迟初始化
*/
val lastName by lazy {
name.split(" ")[1]
}
}
正是因为by lazy跟随的属性可以在运行时算出来,所以序列化的时候他们会被忽略从而减小Json长度。因为延迟初始化属性在对象生成的时候只是一个空引用,Gson从json字符串取回的对象相应属性也是null,Gson把KClass当作JavaClass对待,延迟执行的代码信息也丢了。 如果你一定要既用Gson又要延迟初始化, 百度搜索“@Poko“了解详情。
主角是kotlinx.serialization 首先配置Gradleÿ