千呼万唤始出来,Kotlin官方序列化库终相见(一)(2)

本文详细介绍了Kotlin中的`@Serializable`注解及其在类定义、构造函数、属性序列化方面的使用,包括幕后字段、默认值、可选属性验证、泛型类和套娃序列化等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

}

再次提醒,并不是只有数据类才能序列化,只是为了反序列化时能把类直接打印出来。 敲黑板,@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

@Serializable

class Project(val name: String, val owner: User)

@Serializable

class User(val name: String)

fun main() {

val owner = User(“kotlin”)

val data = Project(“kotlinx.serialization”, owner)

println(Json.encodeToString(data))//{“name”:“kotlinx.serialization”,“owner”:{“name”:“kotlin”}}

}

不压缩重复引用

@Serializable

class Project(val name: String, val owner: User, val maintainer: User)

@Serializable

class User(val name: String)

fun main() {

val owner = User(“kotlin”)

val data = Project(“kotlinx.serialization”, owner, owner)

println(Json.encodeToString(data))

//{“name”:“kotlinx.serialization”,“owner”:{“name”:“kotlin”},“maintainer”:{“name”:“kotlin”}}

}

Kotlin序列化设计用于纯数据的编码和解码。它不支持使用重复的对象引用重建任意对象图。尝试序列化两次引用同一对象的实例,就写入字符串两次。所以不要出现实例的环状引用,那就爆栈了。

泛型类

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

同时我经过多年的收藏目前也算收集到了一套完整的学习资料以及高清详细的Android架构进阶学习导图及笔记分享给大家,希望对想成为架构师的朋友有一定的参考和帮助。

下面是部分资料截图,诚意满满:特别适合有开发经验的Android程序员们学习。

不论遇到什么困难,都不应该成为我们放弃的理由!

如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言,一定会认真查询,修正不足,谢谢。

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

不成体系的学习效果低效漫长且无助。整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

同时我经过多年的收藏目前也算收集到了一套完整的学习资料以及高清详细的Android架构进阶学习导图及笔记分享给大家,希望对想成为架构师的朋友有一定的参考和帮助。

下面是部分资料截图,诚意满满:特别适合有开发经验的Android程序员们学习。

[外链图片转存中…(img-Co5S9pHg-1712382546465)]

不论遇到什么困难,都不应该成为我们放弃的理由!

如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言,一定会认真查询,修正不足,谢谢。

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
回答: Kotlin在使用依赖注入时,可以使用Hilt来实现。Hilt是个基于Dagger的依赖注入框架,专门为Android应用程序设计。\[1\]在序列化和反序列化方面,Kotlin最常用的是Gson。然而,由于Gson无法完全支持Kotlin的特性,社区也维护了些第三方,如Moshi。但是,个人认为随着官方的出现,Moshi可能会逐渐被取代。\[2\]在Kotlin中,如果要使用序列化,可以使用@Serializable注解来标记数据类,并使用Json.decodeFromString函数来进行反序列化操作。\[3\] #### 引用[.reference_title] - *1* [Kotlin 38. Dependency Injection依赖注入以及Hilt在Kotlin中的使用,系列1:依赖注入介绍](https://blog.youkuaiyun.com/zyctimes/article/details/129218437)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [千呼万唤出来,Kotlin官方序列化相见()](https://blog.youkuaiyun.com/weixin_55362248/article/details/121906615)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值