Docs 菜单
Docs 主页
/ /
Atlas Device SDKs
/ /

序列化 - Kotlin SDK

在此页面上

  • Realm 数据类型序列化器
  • 为属性注册序列化器
  • 为文件中的所有出现注册序列化器
  • 自动将 Realm 类型绑定到序列化器
  • 序列化输出示例
  • Atlas 的 EJSON 编码
  • 将 KSerialization 添加到您的项目中
  • Stable Encoder
  • 调用函数
  • 自定义函数凭证
  • 用户配置文件和自定义数据
  • 全文档编码器
  • 必需的导入
  • 定义序列化器
  • 实验性选择加入
  • 调用函数
  • 自定义函数凭证
  • 用户配置文件和自定义数据
  • 其他序列化库

Realm Kotlin SDK 支持 Kotlin 序列化。 您可以使用稳定的序列化器序列化特定的 Realm 数据类型,也可以使用实验性的全文档序列化 API 来序列化用户定义的类。

Realm Kotlin SDK 为 KSerializer 提供了以下数据类型的序列化器:

Realm 数据类型
KSerializer for Type
MutableRealmInt
MutableRealmIntKSerializer::class
RealmAny
RealmAnyKSerializer::class
RealmDictionary
RealmDictionaryKSerializer::class
RealmInstant
RealmInstantKSerializer::class
RealmList
RealmListKSerializer::class
RealmSet
RealmSetKSerializer::class
RealmUUID
RealmUUIDKSerializer::class

序列化器位于io.realm.kotlin.serializers中。

有关Realm如何序列化不同数据类型的示例,请参阅序列化输出示例。

反序列化 Realm 数据类型会生成非托管数据实例。

您可以为特定属性注册序列化器。 使用@Serializable注解绑定到特定 Realm 数据类型序列化器。

class Frog : RealmObject {
var name: String = ""
@Serializable(RealmListKSerializer::class)
var favoritePonds: RealmList<String> = realmListOf()
}

您可以通过将声明添加到文件顶部,为文件中出现的所有该类型注册序列化器:

@file:UseSerializers(RealmSetKSerializer::class)
import io.realm.kotlin.ext.realmSetOf
import io.realm.kotlin.serializers.RealmSetKSerializer
import io.realm.kotlin.types.RealmSet
import kotlinx.serialization.UseSerializers

然后,文件中具有该类型属性的任何对象都可以使用序列化器,而无需单独注册:

// These objects have RealmSet properties that get serializers
// from declaring `@file:UseSerializers(RealmSetKSerializer::class)`.
// No need to individually declare them on every `RealmSet` property in the file.
class Movie : RealmObject {
var movieTitle: String = ""
var actors: RealmSet<String> = realmSetOf()
}
class TVSeries : RealmObject {
var seriesTitle: String = ""
var episodeTitles: RealmSet<String> = realmSetOf()
}

要将所有 Realm 类型自动绑定到其序列化器,您可以在文件顶部添加一个包含所有序列化器的代码片段:

@file:UseSerializers(
MutableRealmIntKSerializer::class,
RealmAnyKSerializer::class,
RealmDictionaryKSerializer::class,
RealmInstantKSerializer::class,
RealmListKSerializer::class,
RealmSetKSerializer::class,
RealmUUIDKSerializer::class
)

这些示例说明了不同 Realm 数据类型如何使用 JSON 编码器进行序列化:

Realm 数据类型
序列化类型和示例
MutableRealmInt
Serializes using a regular integer value.

MutableRealmInt.create(35) serializes to 35
RealmAny
Serializes using a map containing a union of all values and its type.

RealmAny.create("hello world") serializes to {"type": "STRING", "string": "hello world"}

RealmAny.create(20) serializes to {"type": "INT", "int": 20}
RealmDictionary
Serializes using a generic list.

realmDictionaryOf("hello" to "world") serializes to {"hello": "world"}
RealmInstant
Serializes as a BsonDateTime.

RealmInstant.now() serializes to {"$date": {"$numberLong": "<millis>"}}
RealmList
Serializes using a generic list.

realmListOf("hello", world) serializes to ["hello", "world"]
RealmSet
Serializes using a generic list.

realmSetOf("hello", world) serializes to ["hello", "world"]
BsonObjectId 或 ObjectId
Serializes as a BsonObjectId.

ObjectId.create() serializes to {"$oid": <ObjectId bytes as 24-character, big-endian hex string>}
RealmUUID
Serializes as a BsonBinary.

RealmUUID.random() serializes to { "$binary": {"base64": "<payload>", "subType": "<t>"}}
RealmObject

使用用户定义的多态设置进行序列化。 通过 SerializersModule 执行此操作:

val json = Json {
serializersModule = SerializersModule {
polymorphic(RealmObject::class) {
subclass(SerializableSample::class)
}
}
}

1.9.0 版本中的新增功能

直接与 MongoDB Atlas 通信的 Realm Kotlin SDK API 使用 EJSON 编码。 SDK 提供两种类型的 EJSON 编码器:

  • 有限但稳定的编码器

  • 提供完整文档序列化的实验性编码器

使用这些编码器的 API 包括:

Realm Kotlin SDK 的EJSON序列化支持依赖于官方Kotlin序列化库。您必须添加 Kotlin序列化 到您的项目。使用与您的Realm Kotlin SDK版本相同的版本。请参阅 realm-kotlin GitHub存储库中的版本兼容性矩阵 有关每个版本支持的依赖项的信息。

以下示例中的@Serializable注解来自 Kotlin 序列化框架。

稳定版编码器不支持用户定义的类。 您可以将这些参数类型与稳定编码器一起使用:

  • 基元

  • BSON

  • MutableRealmInt

  • RealmUUID

  • ObjectId

  • RealmInstant

  • RealmAny

  • 阵列

  • Collection

  • Map

要返回集合或映射,可以使用BsonArrayBsonDocument

您可以使用带有有效参数类型的稳定编码器调用函数,并对结果进行反序列化。

在此示例中,我们使用两个字符串参数调用getMailingAddress函数,并以BsonDocument形式获取结果:

// The `getMailingAddress` function takes a first name and last name and returns an address as a BsonDocument
val address = user.functions.call<BsonDocument>("getMailingAddress", "Bob", "Smith")
assertEquals(address["street"], BsonString("123 Any Street"))

您可以使用稳定编码器作为映射或 来创建用于Credential 自定义函数身份验证BsonDocument 的 :

val credentials = Credentials.customFunction(
mapOf(
"userId" to 500,
"password" to "securePassword"
)
)
val bsonCredentials = Credentials.customFunction(
BsonDocument(
mapOf(
"userId" to BsonInt32(500),
"password" to BsonString("securePassword")
)
)
)
app.login(credentials)

您可以使用稳定编码器作为BsonDocument来访问用户配置文件或自定义用户数据

val user = app.currentUser!!
val userProfile = user.profileAsBsonDocument()
assertEquals(userProfile["email"], BsonString("my.email@example.com"))
val user = app.currentUser!!
val customUserData = user.customDataAsBsonDocument()
assertEquals(BsonString("blue"), customUserData?.get("favoriteColor"))

全文档编码器使您能够序列化和反序列化用户定义的类。 您可以通过 Atlas 功能为您的类型定义和使用自定义 KSerializer,这些功能使用 EJSON 编码直接与 MongoDB Atlas 通信。 全文档编码器支持上下文序列化器。

重要

这是实验性的

全文档序列化的当前实施是实验性的。 当您的项目使用的Kotlin序列化版本与 Realm 依赖项不同时,调用这些 API 会导致未定义的行为。 请参阅 realm-kotlinGithub 存储库中的版本兼容性矩阵 有关每个版本支持的依赖项的信息。

要使用此功能,请将以下一个或多个导入项添加到您的相关文件中:

import kotlinx.serialization.Serializable
import io.realm.kotlin.annotations.ExperimentalRealmSerializerApi
import org.mongodb.kbson.ExperimentalKBsonSerializerApi
import kotlinx.serialization.modules.SerializersModule
import io.realm.kotlin.serializers.RealmListKSerializer

当您在 Realm Kotlin SDK 中使用序列化时,可以通过以下两种方式之一定义序列化器:

  • @Serializable注解添加到类中

  • 为您的类型定义自定义 KSerializer,并将其传递给相关 API

@Serializable
class Person(
val firstName: String,
val lastName: String
)

如果您要使用上下文序列化器,您可以在AppConfiguration中为应用程序设置自定义 EJSON 序列化器:

@Serializable
class Frogger(
val name: String,
@Contextual
val date: LocalDateTime
)
AppConfiguration.Builder(FLEXIBLE_APP_ID)
.ejson(
EJson(
serializersModule = SerializersModule {
contextual(DateAsIntsSerializer)
}
)
)
.build()

由于全文档序列化 API 是实验性的,因此您必须为所使用的 API 添加相关的@OptIn注释。

@OptIn(ExperimentalRealmSerializerApi::class)

您可以使用带有参数的实验性 API调用函数,或使用自定义序列化器的返回类型。

在此示例中,我们使用序列化的Person对象调用getMailingAddressForPerson函数,并以反序列化的Address对象形式获取结果:

@Serializable
class Address(
val street: String,
val city: String,
val state: String,
val country: String,
val postalCode: String
)
@Serializable
class Person(
val firstName: String,
val lastName: String
)
// The `getMailingAddressForPerson` function takes a Person object and returns an Address object using the experimental serializer
val address = user.functions.call<Address>("getMailingAddressForPerson"){
add(Person("Bob", "Smith"))
}
assertEquals(address.street, "123 Any Street")

提示

稳定序列化器和实验性 API 序列化器的 Atlas Function 调用共享相同的方法名称。 调用不带参数的函数时,必须在实验 API 的指令中提供一个空区块。

val color = user.functions.call<PersonalFavorites>("favouriteColor") {}

您可以使用实验性 API 为自定义函数身份验证定义自定义序列化器:

@Serializable
class CustomUserCredential(
val userId: Int,
val password: String
)

并在创建自定义函数凭证时使用它:

val credentials = Credentials.customFunction(
CustomUserCredential(
userId = 500,
password = "securePassword"
)
)
app.login(credentials)

为用户配置文件或自定义数据定义自定义序列化器:

@Serializable
class UserProfile(
val email: String
)
@Serializable
class UserCustomData(
val favoriteColor: String
)

并在访问用户配置文件或自定义用户数据时使用自定义序列化器:

val user = app.currentUser!!
val userProfile = user.profile<UserProfile>()
assertEquals(userProfile.email, "my.email@example.com")
val user = app.currentUser!!
val customUserData = user.customData<UserCustomData>()
assertEquals("blue", customUserData!!.favoriteColor)

依赖于反射的库使用的序列化方法,例如 GSON 默认不与 SDK 一起使用。

这是因为 SDK 编译器插件将一个隐藏字段注入到对象模型中,前缀为io_realm_kotlin_ 。 SDK 使用此隐藏字段来管理内部对象状态。 任何依赖字段而不是 getter 和 setter 的库都需要忽略这个隐藏字段。

要将 SDK 与 GSON 等外部库结合使用,请使用前缀匹配从序列化中排除隐藏字段:

var gson: Gson = GsonBuilder()
.setExclusionStrategies(object: ExclusionStrategy {
override fun shouldSkipField(f: FieldAttributes?): Boolean =
f?.name?.startsWith("io_realm_kotlin_") ?: false
override fun shouldSkipClass(clazz: Class<*>?): Boolean =
false
})
.create()

后退

响应变更