Kotlin 序列化
在此页面上
Overview
在应用程序中序列化和反序列化Kotlin对象时,可以使用 kotlinx.serialization
库。
该驾驶员提供了一个高效的Bson
序列化器,您可以将其与标有@Serializable
注解的类一起使用,以处理Kotlin对象到BSON数据的序列化。
虽然您可以使用Kotlin序列化Json
库,但Json
序列化器不直接支持ObjectId
等BSON值类型。 您必须提供一个可以处理BSON和JSON之间转换的自定义序列化器。
我们建议安装bson-kotlinx
库以支持自定义编解码器,这些编解码器具有编码默认值、空值和定义类鉴别器的配置。
注意
要学习;了解如何使用Codec
接口而不是kotlinx.serialization
库来指定自定义序列化行为,请参阅编解码器指南。
如果您已经熟悉该库或更喜欢使用一致的方法,则可以选择使用Kotlin序列化。
支持的类型
Kotlin Sync驾驶员支持以下类型:
kotlinx.serialization
库支持的所有Kotlin类型所有 BSON types
将序列化依赖项添加到项目中
您必须安装官方Kotlin序列化库kotlinx.serialization
才能对应用程序中的数据进行序列化和反序列化。 要学习;了解有关此库的更多信息,请参阅 kotlinx.serializationGithub 存储库。
从以下标签页中进行选择,查看如何使用 Gradle或Maven将序列化依赖项添加到项目中:
如果您使用 Gradle 要管理依赖项,请将以下内容添加到build.gradle.kts
依赖项列表中:
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.5.1") implementation("org.mongodb:bson-kotlinx:5.2.0")
如果您使用的是 Maven 要管理依赖项,请将以下内容添加到pom.xml
依赖项列表中:
<dependency> <groupId>org.jetbrains.kotlinx</groupId> <artifactId>kotlinx-serialization-core</artifactId> <version>1.5.1</version> </dependency> <dependency> <groupId>org.mongodb</groupId> <artifactId>bson-kotlinx</artifactId> <version>5.2.0</version> </dependency>
注意
bson-kotlin 依赖项
您还可以选择通过默认编解码器注册表安装bson-kotlin
依赖项。 此依赖项使用反射和编解码器注册表来支持 Kotlin 数据类,但不支持某些 POJO 注解,例如BsonDiscriminator
、 BsonExtraElements
和BsonConstructor
。 要了解更多信息,请参阅 bson-kotlin API 文档。
一般来说,我们建议您安装并使用速度更快的 bson-kotlinx
库进行编解码器配置。
为数据类添加注释
要将类声明为可序列化,请使用@Serializable
注解来注解您的Kotlin数据类。
将数据类标记为可序列化后,就可以在代码中使用这些数据类,就像使用任何其他数据类一样。 Kotlin Sync驾驶员和Kotlin序列化框架处理BSON序列化和反序列化。
此示例显示了带有以下注解的示例数据类:
@Serializable
:将类标记为可序列化。@SerialName
:指定BSON文档中id
和manufacturer
属性的名称。 此注解可用于代替可序列化类中不支持的@BsonId
和@BsonProperty
注解。@Contextual
:标记BSONid
属性以使用内置ObjectIdSerializer
。 驾驶员需要此注解才能正确序列化BSON types 。
data class PaintOrder( // Use instead of @BsonId val id: ObjectId?, val color: String, val qty: Int, val manufacturer: String = "Grumbacher" // Use instead of @BsonProperty )
注意
POJO 注解限制
您不能在标有@Serializable
注解的数据类上使用org.bson.codecs.pojo.annotations
包中的注解。
要学习;了解有关可序列化类和可用注解的更多信息,请参阅可 序列化类 在kotlinx.serialization
库文档中。
自定义序列化器示例
您可以创建自定义序列化器来处理数据在BSON中的表示方式。 Kotlin Sync驾驶员使用kotlinx.serialization
库中的KSerializer
接口来实现自定义序列化器。 您可以将自定义序列化器指定为特定字段的@Serializable
注解的参数。
以下示例介绍如何创建自定义 KSerializer
实例,以将 kotlinx.datetime.Instant
转换为 BsonDateTime
:
object InstantAsBsonDateTime : KSerializer<Instant> { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("InstantAsBsonDateTime", PrimitiveKind.LONG) override fun serialize(encoder: Encoder, value: Instant) { when (encoder) { is BsonEncoder -> encoder.encodeBsonValue(BsonDateTime(value.toEpochMilli())) else -> throw SerializationException("Instant is not supported by ${encoder::class}") } } override fun deserialize(decoder: Decoder): Instant { return when (decoder) { is BsonDecoder -> Instant.ofEpochMilli(decoder.decodeBsonValue().asDateTime().value) else -> throw SerializationException("Instant is not supported by ${decoder::class}") } } }
以下代码显示 PaintOrder
数据类,其中 orderDate
字段具有指定前面代码中定义的自定义序列化器类的注解:
data class PaintOrder( val color: String, val qty: Int, val orderDate: Instant, )
要学习;了解有关本节中提到的方法和类的更多信息,请参阅以下API文档:
KSerializer 在Kotlin文档中
即时 在Kotlin文档中
自定义序列化程序配置
您可以使用org.bson.codecs.kotlinx
包中的KotlinSerializerCodec
类为@Serializable
数据类创建编解码器,并自定义驾驶员在MongoDB中存储的内容。
使用BsonConfiguration
类定义配置,其中可以包括是否对默认值进行编码、对空值进行编码或定义类鉴别器。
要创建自定义编解码器,您的项目必须具有bson-kotlinx
依赖项。 有关安装说明,请参阅本指南的“将序列化依赖项添加到项目中”部分。
您可以使用 KotlinSerializerCodec.create()方法,然后您可以将该编解码器添加到注册表中。
自定义编解码器示例
以下示例展示了如何使用KotlinSerializerCodec.create()
方法创建编解码器,然后将其配置为不对默认值进行编码:
val myCustomCodec = KotlinSerializerCodec.create<PaintOrder>( bsonConfiguration = BsonConfiguration(encodeDefaults = false) ) val registry = CodecRegistries.fromRegistries( CodecRegistries.fromCodecs(myCustomCodec), collection.codecRegistry )
要学习;了解有关本节中提到的方法和类的更多信息,请参阅以下API文档:
多态序列化
Kotlin Sync驾驶员原生支持多态类的序列化和反序列化。 当您使用@Serializable
注解标记密封接口和继承该接口的数据类时,驾驶员会使用KSerializer
实施来处理类型与BSON之间的转换。
当您将多态数据类的实例插入MongoDB时,驾驶员会添加_t
字段,即鉴别器字段。 该字段的值为数据类名称。
多态数据类示例
以下示例创建一个接口和两个继承该接口的数据类。 在数据类中, id
字段标有注释数据类部分中描述的注释:
sealed interface Person { val name: String } data class Student( val id: ObjectId, override val name: String, val grade: Int, ) : Person data class Teacher( val id: ObjectId, override val name: String, val department: String, ) : Person
然后,您可以像往常一样使用数据类执行操作。 以下示例使用Person
接口对集合进行参数化,然后使用多态类Teacher
和Student
执行操作。 检索文档时,驾驶员会根据鉴别器值自动检测类型,并相应地反序列化它们。
val collection = database.getCollection<Person>("school") val teacherDoc = Teacher(ObjectId(), "Vivian Lee", "History") val studentDoc = Student(ObjectId(), "Kate Parker", 10) collection.insertOne(teacherDoc) collection.insertOne(studentDoc) println("Retrieving by using data classes") val resultTeacher = collection.withDocumentClass<Teacher>() .find(Filters.exists("department")) .firstOrNull() println(resultTeacher) val resultStudent = collection.withDocumentClass<Student>() .find(Filters.exists("grade")) .firstOrNull() println(resultStudent) println("\nRetrieving by using Person interface") val resultsPerson = collection.withDocumentClass<Person>().find() resultsPerson.forEach { result -> println(result) } println("\nRetrieving as Document type") val resultsDocument = collection.withDocumentClass<Document>().find() resultsDocument.forEach { result -> println(result) }
Retrieving by using data classes Teacher(id=..., name=Vivian Lee, department=History) Student(id=..., name=Kate Parker, grade=10) Retrieving by using Person interface Teacher(id=..., name=Vivian Lee, department=History) Student(id=..., name=Kate Parker, grade=10) Retrieving as Document type Document{{_id=..., _t=Teacher, name=Vivian Lee, department=History}} Document{{_id=..., _t=Student, name=Kate Parker, grade=10}}
序列化日期和时间
在本节中,您可以学习;了解如何使用Kotlin序列化来处理日期和时间类型。
kotlinx-datetime 库
kotlinx-datetime
是一个Kotlin库,可对日期和时间值的序列化方式提供高级别的控制。 要使用该库,请将kotlinx-datetime
依赖项添加到项目的依赖项列表中。
从以下标签页进行选择,查看如何使用Gradle和Maven包管理器将kotlinx-datetime
依赖项添加到项目中:
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.1")
<dependency> <groupId>org.jetbrains.kotlinx</groupId> <artifactId>kotlinx-datetime-jvm</artifactId> <version>0.6.1</version> </dependency>
要学习;了解有关此库的更多信息,请参阅 kotlinx-datetime存储库 在Github 上。
具有日期和时间的数据类示例
添加库依赖项后,您可以实现kotlinx-datetime
库中的序列化器,将数据类字段值映射到BSON中的预期类型。
在此示例中,驾驶员通过以下行为序列化Appointment
数据类的字段:
name
:驾驶员将该值序列化为string 。date
:驾驶员使用kotlinx-datetime
序列化器,因为该字段具有@Contextual
注解。LocalDate
值被序列化为BSON日期。time
:驾驶员将该值序列化为string ,因为它没有@Contextual
注释。 这是LocalTime
值的默认序列化行为。
data class Appointment( val name: String, val date: LocalDate, val time: LocalTime, )
以下示例将Appointment
数据类的实例插入appointments
集合:
val collection = database.getCollection<Appointment>("appointments") val apptDoc = Appointment( "Daria Smith", LocalDate(2024, 10, 15), LocalTime(hour = 11, minute = 30) ) collection.insertOne(apptDoc)
在MongoDB中,LocalDate
值存储为BSON日期,time
字段默认序列化为string存储:
{ "_id": ..., "name": "Daria Smith", "date": { "$date": "2024-10-15T00:00:00.000Z" }, "time": "11:30", }