序列化 - Kotlin SDK
在此页面上
Realm Kotlin SDK 支持 Kotlin 序列化。 您可以使用稳定的序列化器序列化特定的 Realm 数据类型,也可以使用实验性的全文档序列化 API 来序列化用户定义的类。
Realm 数据类型序列化器
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 = "" var favoritePonds: RealmList<String> = realmListOf() }
为文件中的所有出现注册序列化器
您可以通过将声明添加到文件顶部,为文件中出现的所有该类型注册序列化器:
class) (RealmSetKSerializer::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 类型绑定到序列化器
要将所有 Realm 类型自动绑定到其序列化器,您可以在文件顶部添加一个包含所有序列化器的代码片段:
( 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 执行此操作:
|
Atlas 的 EJSON 编码
1.9.0 版本中的新增功能。
直接与 MongoDB Atlas 通信的 Realm Kotlin SDK API 使用 EJSON 编码。 SDK 提供两种类型的 EJSON 编码器:
有限但稳定的编码器
提供完整文档序列化的实验性编码器
使用这些编码器的 API 包括:
App Services Function 调用
具有自定义函数身份验证的档案
用户配置文件和自定义用户数据
将 KSerialization 添加到您的项目中
Realm Kotlin SDK 的EJSON序列化支持依赖于官方Kotlin序列化库。您必须添加 Kotlin序列化 到您的项目。使用与您的Realm Kotlin SDK版本相同的版本。请参阅 realm-kotlin GitHub存储库中的版本兼容性矩阵 有关每个版本支持的依赖项的信息。
以下示例中的@Serializable
注解来自 Kotlin 序列化框架。
Stable Encoder
稳定版编码器不支持用户定义的类。 您可以将这些参数类型与稳定编码器一起使用:
基元
BSON
MutableRealmInt
RealmUUID
ObjectId
RealmInstant
RealmAny
阵列
Collection
Map
要返回集合或映射,可以使用BsonArray
或BsonDocument
。
调用函数
您可以使用带有有效参数类型的稳定编码器调用函数,并对结果进行反序列化。
在此示例中,我们使用两个字符串参数调用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
class Person( val firstName: String, val lastName: String )
如果您要使用上下文序列化器,您可以在AppConfiguration
中为应用程序设置自定义 EJSON 序列化器:
class Frogger( val name: String, val date: LocalDateTime ) AppConfiguration.Builder(FLEXIBLE_APP_ID) .ejson( EJson( serializersModule = SerializersModule { contextual(DateAsIntsSerializer) } ) ) .build()
实验性选择加入
由于全文档序列化 API 是实验性的,因此您必须为所使用的 API 添加相关的@OptIn
注释。
调用函数
您可以使用带有参数的实验性 API调用函数,或使用自定义序列化器的返回类型。
在此示例中,我们使用序列化的Person
对象调用getMailingAddressForPerson
函数,并以反序列化的Address
对象形式获取结果:
class Address( val street: String, val city: String, val state: String, val country: String, val postalCode: String ) 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 为自定义函数身份验证定义自定义序列化器:
class CustomUserCredential( val userId: Int, val password: String )
并在创建自定义函数凭证时使用它:
val credentials = Credentials.customFunction( CustomUserCredential( userId = 500, password = "securePassword" ) ) app.login(credentials)
用户配置文件和自定义数据
为用户配置文件或自定义数据定义自定义序列化器:
class UserProfile( val email: String )
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()