Docs Menu
Docs Home
/ /
Realm

Serialización - SDK de Kotlin

El SDK de Kotlin de Realm admite la serialización de Kotlin. Puede serializar tipos de datos específicos de Realm mediante serializadores estables o clases definidas por el usuario con una API experimental de serialización de documentos completos.

El Realm Kotlin SDK proporciona serializadores para los siguientes tipos de datos para KSerializer:

Tipo de datos de reino
KSerializer para tipo

MutableRealmInt

MutableRealmIntKSerializer::class

RealmAny

RealmAnyKSerializer::class

RealmDictionary

RealmDictionaryKSerializer::class

RealmInstant

RealmInstantKSerializer::class

RealmList

RealmListKSerializer::class

RealmSet

RealmSetKSerializer::class

RealmUUID

RealmUUIDKSerializer::class

Los serializadores se encuentran en io.realm.kotlin.serializers.

Para ver ejemplos de cómo Realm serializa los diferentes tipos de datos, consulte Ejemplos de salida de serialización.

La deserialización de los tipos de datos de Realm genera instancias de datos no administradas.

Puedes registrar un serializador para una propiedad específica. Usa la anotación @Serializable para enlazar con un serializador de tipo de datos de Realm específico.

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

Puede registrar un serializador para todas las ocurrencias de ese tipo dentro de un archivo agregando la declaración en la parte superior del archivo:

@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

Luego, cualquier objeto que tenga propiedades de ese tipo dentro del archivo puede usar el serializador sin registrarlo individualmente:

// 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()
}

Para vincular automáticamente todos los tipos Realm con sus serializadores, puedes añadir un fragmento que contenga todos los serializadores en la parte superior de un archivo:

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

Estos ejemplos ilustran cómo los diferentes tipos de datos de Realm se serializan usando un codificador JSON:

Tipo de datos de reino
Tipo de serialización y ejemplo

MutableRealmInt

Serializes using a regular integer value.

MutableRealmInt.create(35) serializes to 35

Reino cualquiera

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}

Diccionario del reino

Serializes using a generic list.

realmDictionaryOf("hello" to "world") serializes to {"hello": "world"}

Reino instantáneo

Serializes as a BsonDateTime.

RealmInstant.now() serializes to {"$date": {"$numberLong": "<millis>"}}

Lista de reinos

Serializes using a generic list.

realmListOf("hello", world) serializes to ["hello", "world"]

Conjunto de reinos

Serializes using a generic list.

realmSetOf("hello", world) serializes to ["hello", "world"]

BsonObjectId o ObjectId

Serializes as a BsonObjectId.

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

UUID del reino

Serializes as a BsonBinary.

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

Objeto de reino

Serializa utilizando la configuración polimórfica definida por el usuario. Para ello, utilice el módulo Serializers:

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

Nuevo en la versión 1.9.0.

Las API del SDK de Realm Kotlin que se comunican directamente con MongoDB Atlas utilizan codificación EJSON. El SDK ofrece dos tipos de codificadores EJSON:

  • Un codificador limitado pero estable

  • Un codificador experimental que ofrece serialización completa de documentos

Las API que utilizan estos codificadores incluyen:

La compatibilidad con la serialización EJSON del SDK de Kotlin de Realm depende de la biblioteca oficial de serialización de Kotlin. Debe agregar la serialización de Kotlin.a tu proyecto. Usa la misma versión que la del SDK de Kotlin de Realm. Consulta la Matriz de Compatibilidad de Versiones en el repositorio de GitHub de realm-kotlin para obtener información sobre las dependencias compatibles con cada versión.

La anotación @Serializable en los siguientes ejemplos proviene del marco de serialización Kotlin.

El codificador estable no admite clases definidas por el usuario. Puede usar estos tipos de argumentos con el codificador estable:

  • Primitivos

  • BSON

  • MutableRealmInt

  • RealmUUID

  • ObjectId

  • RealmInstant

  • RealmAny

  • Arreglo

  • Colección

  • Map

Para devolver una colección o un mapa, puede utilizar BsonArray o BsonDocument.

Puede llamar a una función utilizando el codificador estable con un tipo de argumento válido y deserializar el resultado.

En este ejemplo, llamamos a la función getMailingAddress con dos argumentos de cadena y obtenemos el resultado como 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"))

Puede crear un Credential para usar con la autenticación de funciones personalizadas utilizando el codificador estable como un mapa o BsonDocument un:

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)

Puede acceder a un perfil de usuario o a datos de usuario personalizados utilizando el codificador estable BsonDocument como:

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"))

El codificador de documentos completos permite serializar y deserializar clases definidas por el usuario. Puede definir y usar KSerializers personalizados para su tipo con funciones de Atlas que se comunican directamente con MongoDB Atlas mediante codificación EJSON. El codificador de documentos completos admite serializadores contextuales.

Importante

Esto es experimental

La implementación actual de la serialización completa de documentos es experimental. Llamar a estas API cuando el proyecto utiliza una versión de serialización de Kotlin diferente a la de la dependencia de Realm provoca un comportamiento indefinido. Consulta la Matriz de compatibilidad de versiones en el repositorio de GitHub realm-kotlin para obtener información sobre las dependencias compatibles con cada versión.

Para utilizar esta función, agregue una o más de las siguientes importaciones a su archivo según corresponda:

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

Cuando usa la serialización en el SDK de Kotlin de Realm, puede definir un serializador de una de dos maneras:

  • Agregar la anotación @Serializable a una clase

  • Define un KSerializer personalizado para tu tipo y pásalo a la API correspondiente

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

Puedes configurar un serializador EJSON personalizado para tu aplicación en el AppConfiguration, como en un caso donde desees utilizar un serializador contextual:

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

Debido a que la API de serialización de documentos completos es experimental, debe agregar las anotaciones @OptIn relevantes para las API que utilice.

@OptIn(ExperimentalRealmSerializerApi::class)

Puede llamar a una función utilizando la API experimental con argumentos o tipos de retorno que utilizan serializadores personalizados.

En este ejemplo, llamamos a la función getMailingAddressForPerson con un objeto Person serializado y obtenemos el resultado como un objeto Address deserializado:

@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")

Tip

Las llamadas a funciones Atlas para el serializador estable y el serializador de la API experimental comparten el mismo nombre de método. Al invocar una función sin parámetros, se debe proporcionar un bloque vacío en la instrucción para la API experimental.

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

Puedes definir un serializador personalizado para la autenticación de función personalizada usando la API experimental:

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

Y úselo al crear una credencial de función personalizada:

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

Defina un serializador personalizado para el perfil de usuario o datos personalizados:

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

Y use el serializador personalizado al acceder al perfil de usuario o a los datos de usuario personalizados:

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)

Los métodos de serialización utilizados por bibliotecas que dependen de la reflexión, como GSON, no funcionan con el SDK de forma predeterminada.

Esto se debe a que el complemento del compilador del SDK inyecta un campo oculto en los modelos de objetos, con el prefijo io_realm_kotlin_. El SDK utiliza este campo oculto para gestionar el estado interno de los objetos. Cualquier biblioteca que utilice campos en lugar de métodos getters y setters debe ignorar este campo oculto.

Para utilizar el SDK con bibliotecas externas como GSON, excluya los campos ocultos de la serialización mediante una coincidencia de prefijo:

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()

Volver

Reaccionar a los cambios