Menu Docs
Página inicial do Docs
/ /
Atlas Device SDKs
/ /

Serialização - Kotlin SDK

Nesta página

  • Serializadores de tipo de dados Realm
  • Registrar um serializador para uma propriedade
  • Registrar um serializador para todas as ocorrências em um arquivo
  • Vincular automaticamente tipos de Realm a serializadores
  • Exemplos de saída de serialização
  • Codificação EJSON para Atlas
  • Adicionar KSerialization ao seu projeto
  • Codificador estável
  • Chamar uma função
  • Credenciais de função personalizada
  • Perfil de usuário e dados personalizados
  • Codificador de documento completo
  • Importações necessárias
  • Definir um serializador
  • Aceitação experimental
  • Chamar uma função
  • Credenciais de função personalizada
  • Perfil de usuário e dados personalizados
  • Outras bibliotecas de serialização

O Realm Kotlin SDK suporta serialização de Kotlin. Você pode serializar tipos de dados específicos do Realm usando serializadores estáveis ou classes definidas pelo usuário com uma API experimental de serialização de documento completo.

O Realm Kotlin SDK fornece serializadores para os seguintes tipos de dados para KSerializer:

Tipo de dados Realm
KSerializer para tipo
MutableRealmInt
MutableRealmIntKSerializer::class
RealmAny
RealmAnyKSerializer::class
RealmDictionary
RealmDictionaryKSerializer::class
RealmInstant
RealmInstantKSerializer::class
RealmList
RealmListKSerializer::class
RealmSet
RealmSetKSerializer::class
RealmUUID
RealmUUIDKSerializer::class

Os serializadores estão localizados em io.realm.kotlin.serializers.

Para obter exemplos de como o Realm serializa os diferentes tipos de dados, consulte Exemplos de saída de serialização.

A desserialização de tipos de dados de Realm gera instâncias de dados não gerenciadas.

Você pode registrar um serializador para uma propriedade específica. Use a anotação @Serializable para vincular-se a um serializador de tipo de dados Realm específico.

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

Você pode registrar um serializador para todas as ocorrências desse tipo em um arquivo adicionando a declaração ao topo do arquivo:

@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

Em seguida, quaisquer objetos que tenham propriedades desse tipo dentro do arquivo podem usar o serializador sem registrá-lo 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 automaticamente todos os tipos de Realm a seus serializadores, você pode adicionar um trecho contendo todos os serializadores ao topo de um arquivo:

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

Esses exemplos ilustram como os diferentes tipos de dados do Realm são serializados usando um codificador JSON:

Tipo de dados Realm
Tipo de serialização e exemplo
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}
Dicionário Realm
Serializes using a generic list.

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

RealmInstant.now() serializes to {"$date": {"$numberLong": "<millis>"}}
Lista de domínios
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 ou 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

Serializa usando a configuração polimórfica definida pelo usuário. Faça isso por meio do SerializersModule:

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

Novidades na versão 1.9.0.

As API do Realm Kotlin SDK que se comunicam diretamente com o MongoDB Atlas usam a codificação EJSON. O SDK oferece dois tipos de codificadores EJSON:

  • Um codificador limitado, mas estável

  • Um codificador experimental que oferece serialização completa de documentos

As API que usam esses codificadores incluem:

O suporte à serialização EJSON do Realm Kotlin SDK depende da biblioteca oficial de serialização do Kotlin . Você deve adicionar serialização do Kotlin ao seu projeto. Use a mesma versão usada na versão do Realm Kotlin SDK . Consulte a Matriz de compatibilidade de versão no repositório realm-kotlin do GitHub para obter informações sobre as dependências suportadas de cada versão.

A anotação @Serializable nos exemplos a seguir vem da estrutura de serialização do Kotlin.

O codificador estável não oferece suporte a classes definidas pelo usuário. Você pode usar esses tipos de argumentos com o codificador estável:

  • Primitivos

  • BSON

  • MutableRealmInt

  • RealmUUID

  • ObjectId

  • RealmInstant

  • RealmAny

  • Array

  • collection

  • Map

Para retornar uma collection ou mapa, você pode usar BsonArray ou BsonDocument.

Você pode chamar uma função usando o codificador estável com um tipo de argumento válido e desserializar o resultado.

Neste exemplo, chamamos a função getMailingAddress com dois argumentos de string e obtemos o 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"))

Você pode criar um Credential para utilizar com autenticação de função personalizada utilizando o codificador estável como um mapa ou um 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)

Você pode acessar um perfil de usuário ou dados de usuário personalizados usando o codificador estável como 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"))

O codificador de documento completo permite serializar e desserializar classes definidas pelo usuário. Você pode definir e usar KSerializers personalizados para seu tipo com funcionalidades do Atlas que se comunicam diretamente com o MongoDB Atlas usando a codificação EJSON. O codificador de documento completo oferece suporte a serializadores contextuais.

Importante

Isso é experimental

A implementação atual da serialização completa de documento é experimental. Chamar essas APIs quando seu projeto usa uma versão diferente da Serialização de Kotlin da dependência do Realm causa um comportamento indefinido. Consulte a Matriz de compatibilidade de versão no Github repositório do realm-kotlin do para obter informações sobre as dependências suportadas de cada versão.

Para usar esse recurso, adicione uma ou mais das seguintes importações ao seu arquivo, conforme relevante:

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

Ao usar a serialização no Realm Kotlin SDK, você pode definir um serializador de duas maneiras:

  • Adicione a anotação @Serializable a uma classe

  • Defina um KSerializer personalizado para o seu tipo e passe-o para a API relevante

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

Você pode definir um serializador EJSON personalizado para seu aplicativo no AppConfiguration, como no caso em que você deseja utilizar um serializador contexto:

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

Como a API de serialização de documentos completa é experimental, você deve adicionar as anotações @OptIn relevantes para as APIs que você usa.

@OptIn(ExperimentalRealmSerializerApi::class)

Você pode chamar uma função usando a API experimental com argumentos ou tipos de retorno que usam serializadores personalizados.

Neste exemplo, chamamos a função getMailingAddressForPerson com um objeto Person serializado e obtemos o resultado como um objeto Address desserializado:

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

Dica

As chamadas da Função de Realm para o serializador estável e o serializador de API experimental compartilham o mesmo nome de método. Ao invocar uma função sem parâmetros, você deve fornecer um bloco vazio na instrução para a API experimental.

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

Você pode definir um serializador personalizado para autenticação de função personalizada usando a API experimental:

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

E use-o ao criar uma credencial de função personalizada:

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

Defina um serializador personalizado para perfil de usuário ou dados personalizados:

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

E use o serializador personalizado ao acessar o perfil do usuário ou os dados personalizados do usuário:

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)

Métodos de serialização usados por bibliotecas que dependem de reflexão, como GSON não funcionam com o SDK por padrão.

Isso ocorre porque o plug-in do compilador SDK injeta um campo oculto nos modelos de objetos, prefixado com io_realm_kotlin_. O SDK usa esse campo oculto para managed o estado do objeto interno. Qualquer biblioteca que dependa de campos em vez de getters e setters precisa ignorar esse campo oculto.

Para usar o SDK com bibliotecas externas, como GSON, exclua os campos ocultos da serialização usando uma correspondência de prefixo:

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

Voltar

Reagir às alterações