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.
Serializadores de tipos de datos de Realm
El Realm Kotlin SDK proporciona serializadores para los siguientes tipos de datos para KSerializer:
Tipo de datos de reino | KSerializer para tipo |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
Registrar un serializador para una propiedad
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 = "" var favoritePonds: RealmList<String> = realmListOf() }
Registrar un serializador para todas las ocurrencias en un archivo
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:
(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() }
Vincular automáticamente tipos de dominio a serializadores
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:
( MutableRealmIntKSerializer::class, RealmAnyKSerializer::class, RealmDictionaryKSerializer::class, RealmInstantKSerializer::class, RealmListKSerializer::class, RealmSetKSerializer::class, RealmUUIDKSerializer::class )
Ejemplos de salida de serialización
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: |
Codificación EJSON para Atlas
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:
Llamadas de función deservicios de aplicaciones
Credenciales con autenticación de función personalizada
Perfil de usuario y datos de usuario personalizados
Agregue KSerialization a su proyecto
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.
Codificador estable
El codificador estable no admite clases definidas por el usuario. Puede usar estos tipos de argumentos con el codificador estable:
Primitivos
BSON
MutableRealmIntRealmUUIDObjectIdRealmInstantRealmAnyArreglo
Colección
Map
Para devolver una colección o un mapa, puede utilizar BsonArray o BsonDocument.
Llamar a una función
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"))
Credenciales de funciones personalizadas
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)
Perfil de usuario y datos personalizados
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"))
Codificador de documentos completos
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.
Importaciones requeridas
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
Definir un serializador
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
@Serializablea una claseDefine un KSerializer personalizado para tu tipo y pásalo a la API correspondiente
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:
class Frogger( val name: String, val date: LocalDateTime ) AppConfiguration.Builder(FLEXIBLE_APP_ID) .ejson( EJson( serializersModule = SerializersModule { contextual(DateAsIntsSerializer) } ) ) .build()
Opt-In experimental
Debido a que la API de serialización de documentos completos es experimental, debe agregar las anotaciones @OptIn relevantes para las API que utilice.
Llamar a una función
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:
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")
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") {}
Credenciales de funciones personalizadas
Puedes definir un serializador personalizado para la autenticación de función personalizada usando la API experimental:
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)
Perfil de usuario y datos personalizados
Defina un serializador personalizado para el perfil de usuario o datos personalizados:
class UserProfile( val email: String )
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)
Otras bibliotecas de serialización
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()