*/
val lastName by lazy {
name.split(" ")[1]
}
}
正是因为by lazy跟随的属性可以在运行时算出来,所以序列化的时候他们会被忽略从而减小Json长度。因为延迟初始化属性在对象生成的时候只是一个空引用,Gson从json字符串取回的对象相应属性也是null,Gson把KClass当作JavaClass对待,延迟执行的代码信息也丢了。 如果你一定要既用Gson又要延迟初始化, 百度搜索“@Poko“了解详情。
主角是kotlinx.serialization 首先配置Gradle:
//build.gradle
plugins {
id ‘org.jetbrains.kotlin.jvm’ version ‘1.4.20’
id ‘org.jetbrains.kotlin.plugin.serialization’ version ‘1.4.20’
}
repositories {
// Artifacts are also available on Maven Central
jcenter()
}
dependencies {
implementation “org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1”
}
对于JSON,我们使用Json.encodeToString扩展功能对数据进行编码。它将可序列化的对象作为其参数在后台进行序列化,并将其编码为JSON字符串。 让我们从描述项目的类开始,并尝试获取其JSON表示形式。
@Serializable
data class Project(val name: String, val language: String)
fun main() {
val data = Project(“kotlinx.serialization”, “Kotlin”)
println(Json.encodeToString(data))
//打印{“name”:“kotlinx.serialization”,“language”:“Kotlin”}
val data = Json.decodeFromString(“”"
{“name”:“kotlinx.serialization”,“language”:“Kotlin”}
“”")
println(data)//Project(name=kotlinx.serialization, language=Kotlin)
}
再次提醒,并不是只有数据类才能序列化,只是为了反序列化时能把类直接打印出来。 敲黑板,@Serializable,可以加参数指定我们自定义的序列化器,无参数时使用系统给的Serializer。 幕后字段序列化 仅对有后备字段的类的属性进行序列化,因此具有getter / setter但却没有幕后字段的属性不会被序列化,被委托的属性也不会被序列化。
@Serializable
class Project(
// name is a property with backing field – serialized
var name: String
) {
var stars: Int = 0 // property with a backing field – serializedval
path: String // getter only, no backing field – not serialized
get() = “kotlin/$name”
var id by ::name // delegated property – not serialized
}
fun main() {
val data = Project(“kotlinx.serialization”).apply { stars = 9000 }
println(Json.encodeToString(data))
//{“name”:“kotlinx.serialization”,“stars”:9000}
}
如果我们想定义Project类,使其采用路径字符串,然后将其解构为相应的属性,则我们可能很想编写类似以下代码的内容:
@Serializable
class Project(path: String) {
val owner: String = path.substringBefore(‘/’)
val name: String = path.substringAfter(‘/’)
}
此类无法编译,因为@Serializable注解要求该类的主构造函数的所有参数均为属性。一个简单的解决方法是使用类的属性定义一个私有的主构造函数,然后将所需的构造函数转换为辅助构造函数。
@Serializable
class Project private constructor(val owner: String, val name: String) {
constructor(path: String) : this(
owner = path.substringBefore(‘/’),
name = path.substringAfter(‘/’)
)
val path: String
get() = “ o w n e r / owner/ owner/name”
}
fun main() {
println(Json.encodeToString(Project(“kotlin/kotlinx.serialization”)))
//{“owner”:“kotlin”,“name”:“kotlinx.serialization”}
}
path不具有幕后字段,不会被序列化。 数据验证 另一种情况是你可能想引入不带属性的主构造函数参数,在将其值存储到属性之前对其进行验证。为了使其可序列化,应该在主构造函数中将其替换为属性,然后将验证移至init {…}块中:
@Serializable
class Project(val name: String) {
init {
require(name.isNotEmpty()) { “name cannot be empty” }
}
}
fun main() {
val data = Json.decodeFromString(“”"
{“name”:“”}
“”")//Exception in thread “main” java.lang.IllegalArgumentException: name cannot be empty
println(data)
}
默认值
默认值属性反序列化时会被自动填充,序列化时不会被写入json,目的还是节省空间和带宽,在大多数实际场景中,此类配置可以减少视觉混乱,并节省要序列化的数据量。
0@Serializable
data class Project(val name: String, val language: String = “Kotlin”)
fun main() {
val data = Json.decodeFromString(“”"
{“name”:“kotlinx.serialization”}
“”")
println(data)//Project(name=kotlinx.serialization, language=Kotlin)
val data1 = Project(“kotlinx.serialization”)
println(Json.encodeToString(data1))//{“name”:“kotlinx.serialization”}
}
另一种类似情况是可空属性默认值为null
@Serializable
class Project(val name: String, val renamedTo: String? = null)
fun main() {
val data = Project(“kotlinx.serialization”)
println(Json.encodeToString(data))//{“name”:“kotlinx.serialization”}
}
当输入中存在可选属性时,该属性的相应初始化器不会调用。此功能是为提高性能而设计的,因此请注意不要依赖初始化程序中的副作用。
fun computeLanguage(): String {
println(“Computing”)
return “Kotlin”
}
@Serializable
data class Project(val name: String, val language: String = computeLanguage())
fun main() {
val data = Json.decodeFromString(“”"
{“name”:“kotlinx.serialization”,“language”:“Kotlin”}
“”")
println(data)//Project(name=kotlinx.serialization, language=Kotlin)
}
由于在输入中指定了language属性,因此在输出中看不到“计算”字符串。
@Required修饰的属性其值必须显式指明。
@Serializable
data class Project(val name: String, @Required val language: String = “Kotlin”)
fun main() {
val data = Json.decodeFromString(“”"
{“name”:“kotlinx.serialization”}
“”")
println(data)//Exception in thread “main” kotlinx.serialization.MissingFieldException: Field ‘language’ is required, but it was missing
}
@Transient修饰的属性不会被序列化,反序列化时也不能被指定。
@Serializable
data class Project(val name: String, @Transient val language: String = “Kotlin”)
fun main() {
val data = Json.decodeFromString(“”"
{“name”:“kotlinx.serialization”,“language”:“Kotlin”}
“”")/**
*Exception in thread “main” kotlinx.serialization.json.internal.JsonDecodingException:
*Unexpected JSON token at offset 60: Encountered an unknown key ‘language’.
*Use ‘ignoreUnknownKeys = true’ in ‘Json {}’ builder to ignore unknown keys.
*/
println(data)
}
Kt的序列化框架是严格支持Kt的类型系统的,所以下面的代码有异常:
@Serializable
data class Project(val name: String, val language: String = “Kotlin”)
fun main() {
val data = Json.decodeFromString(“”"
{“name”:“kotlinx.serialization”,“language”:null}
“”")//Exception in thread “main” kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 52: Expected string literal but ‘null’ literal was found.
//Use ‘coerceInputValues = true’ in 'Json {}` builder to coerce nulls to default values.
println(data)
}
套娃序列化
可序列化的类可以在其可序列化属性中引用其他类。被引用的类也必须标记为@Serializable
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
这里我特地整理了一份《Android开发核心知识点笔记》,里面就包含了自定义View相关的内容
除了这份笔记,还给大家分享 Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这几块的内容。非常适合近期有面试和想在技术道路上继续精进的朋友。
分享上面这些资源,希望可以帮助到大家提升进阶,如果你觉得还算有用的话,不妨把它们推荐给你的朋友~
喜欢本文的话,给我点个小赞、评论区留言或者转发支持一下呗~
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
最后
这里我特地整理了一份《Android开发核心知识点笔记》,里面就包含了自定义View相关的内容
[外链图片转存中…(img-0fjPWvVV-1713527924355)]
除了这份笔记,还给大家分享 Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这几块的内容。非常适合近期有面试和想在技术道路上继续精进的朋友。
[外链图片转存中…(img-Ud5E2LSX-1713527924356)]
分享上面这些资源,希望可以帮助到大家提升进阶,如果你觉得还算有用的话,不妨把它们推荐给你的朋友~
喜欢本文的话,给我点个小赞、评论区留言或者转发支持一下呗~
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!