Docs 菜单
Docs 主页
/ / /
Kotlin Sync 驱动程序
/ /

数据序列化

在应用程序中序列化和反序列化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.serialization Github存储库。

从以下标签页中进行选择,查看如何使用 GradleMaven将序列化依赖项添加到项目中:

如果使用 Gradle 管理依赖项,请将以下内容添加到 build.gradle.kts 依赖项列表中:

build.gradle.kts
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.5.1")
implementation("org.mongodb:bson-kotlinx:5.1.4")

如果使用Maven管理依赖项,请将以下内容添加到 pom.xml 依赖项列表中:

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.1.4</version>
</dependency>

注意

bson-kotlin 依赖项

您还可以选择通过默认编解码器注册表安装 bson-kotlin 依赖项。此依赖项使用反射和编解码器注册表来支持Kotlin数据类,但不支持某些 POJO 注解,例如 BsonDiscriminatorBsonExtraElementsBsonConstructor。要学习;了解更多信息,请参阅 bson-kotlin API文档。

一般来说,我们建议您安装并使用速度更快的 bson-kotlinx 库进行编解码器配置。

要将类声明为可序列化,请使用@Serializable注解来注解您的Kotlin数据类。

将数据类标记为可序列化后,就可以在代码中使用这些数据类,就像使用任何其他数据类一样。 Kotlin Sync驾驶员和Kotlin序列化框架处理BSON序列化和反序列化。

此示例显示了带有以下注解的示例数据类:

  • @Serializable:将类标记为可序列化。

  • @SerialName:指定BSON文档中idmanufacturer属性的名称。 此注解可用于代替可序列化类中不支持的@BsonId@BsonProperty注解。

  • @Contextual:标记BSON id属性以使用内置ObjectIdSerializer 。 驾驶员需要此注解才能正确序列化BSON types 。

@Serializable
data class PaintOrder(
@SerialName("_id") // Use instead of @BsonId
@Contextual val id: ObjectId?,
val color: String,
val qty: Int,
@SerialName("brand")
val manufacturer: String? = null // 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 字段具有指定前面代码中定义的自定义序列化器类的注解:

@Serializable
data class PaintOrder(
val color: String,
val qty: Int,
@Serializable(with = InstantAsBsonDateTime::class)
val orderDate: Instant,
)

要学习;了解有关本节中提到的方法和类的更多信息,请参阅以下API文档:

您可以使用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字段标有注释数据类部分中描述的注释:

@Serializable
sealed interface Person {
val name: String
}
@Serializable
data class Student(
@Contextual
@SerialName("_id")
val id: ObjectId,
override val name: String,
val grade: Int,
) : Person
@Serializable
data class Teacher(
@Contextual
@SerialName("_id")
val id: ObjectId,
override val name: String,
val department: String,
) : Person

然后,您可以像往常一样使用数据类执行操作。 以下示例使用Person接口对集合进行参数化,然后使用多态类TeacherStudent执行操作。 检索文档时,驾驶员会根据鉴别器值自动检测类型,并相应地反序列化它们。

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}}

后退

Data Formats

在此页面上