---
title: "Serialization em Kotlin: O que É e Como Funciona | Kotlin Brasil"
url: "https://kotlin.dev.br/glossario/serialization/"
markdown_url: "https://kotlin.dev.br/glossario/serialization.MD"
description: "Saiba o que é kotlinx.serialization, como converter objetos Kotlin para JSON, Protobuf e outros formatos."
date: "2025-08-18"
author: "Karina Melo"
---

# Serialization em Kotlin: O que É e Como Funciona | Kotlin Brasil

Saiba o que é kotlinx.serialization, como converter objetos Kotlin para JSON, Protobuf e outros formatos.


## O que é Serialization em Kotlin?

**Serialization** (serialização) é o processo de converter objetos Kotlin em um formato que pode ser armazenado ou transmitido (como JSON, Protobuf ou CBOR), e **desserializacao** é o processo inverso. O **kotlinx.serialization** é a biblioteca oficial do Kotlin para essa tarefa, gerando código de serialização em **tempo de compilação** usando um plugin do compilador.

Diferente de bibliotecas baseadas em reflexao (como Gson), kotlinx.serialization é mais rápida, type-safe e funciona em todas as plataformas Kotlin (JVM, iOS, JavaScript, WASM).

### Configuração do projeto

```kotlin
// build.gradle.kts
plugins {
    kotlin("jvm") version "1.9.22"
    kotlin("plugin.serialization") version "1.9.22"
}

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
}
```

### Uso básico com JSON

```kotlin
import kotlinx.serialization.*
import kotlinx.serialization.json.*

@Serializable
data class Usuario(
    val nome: String,
    val idade: Int,
    val email: String
)

fun main() {
    val usuario = Usuario("Ana", 30, "ana@email.com")

    // Serializar: objeto -> JSON string
    val json = Json.encodeToString(usuario)
    println(json)
    // {"nome":"Ana","idade":30,"email":"ana@email.com"}

    // Desserializar: JSON string -> objeto
    val objeto = Json.decodeFromString<Usuario>(json)
    println(objeto)
    // Usuario(nome=Ana, idade=30, email=ana@email.com)
}
```

A anotacao `@Serializable` instrui o plugin do compilador a gerar um serializer para a classe. Sem ela, a classe não pode ser serializada.

### Customizando nomes de campos

```kotlin
@Serializable
data class Produto(
    @SerialName("nome_produto")
    val nome: String,

    @SerialName("preco_unitario")
    val preco: Double,

    @SerialName("em_estoque")
    val emEstoque: Boolean
)

fun main() {
    val produto = Produto("Teclado", 299.90, true)
    val json = Json.encodeToString(produto)
    println(json)
    // {"nome_produto":"Teclado","preco_unitario":299.9,"em_estoque":true}
}
```

### Valores opcionais e padrão

```kotlin
@Serializable
data class Configuração(
    val tema: String = "claro",
    val fontSize: Int = 14,
    val idioma: String = "pt-BR"
)

fun main() {
    val json = Json { encodeDefaults = false }

    // Serializar: campos com valor padrao podem ser omitidos
    val config = Configuração()
    println(json.encodeToString(config))
    // {} (campos com valor padrao omitidos)

    // Desserializar: campos ausentes usam valor padrao
    val configParcial = json.decodeFromString<Configuração>("""{"tema":"escuro"}""")
    println(configParcial)
    // Configuração(tema=escuro, fontSize=14, idioma=pt-BR)
}
```

### Configurando o Json

O objeto `Json` pode ser customizado com várias opções:

```kotlin
val jsonConfig = Json {
    prettyPrint = true              // JSON formatado com indentacao
    isLenient = true                // Aceita JSON nao estritamente valido
    ignoreUnknownKeys = true        // Ignora campos desconhecidos
    encodeDefaults = true           // Inclui campos com valor padrao
    coerceInputValues = true        // Coerce valores incorretos para padrao
    explicitNulls = false           // Omite campos null
    namingStrategy = JsonNamingStrategy.SnakeCase // Converte camelCase para snake_case
}

@Serializable
data class Resposta(
    val statusCode: Int,
    val mensagem: String,
    val dados: String? = null
)

fun main() {
    val json = """
        {
            "status_code": 200,
            "mensagem": "Sucesso",
            "campo_extra": "ignorado"
        }
    """.trimIndent()

    val resposta = jsonConfig.decodeFromString<Resposta>(json)
    println(resposta)
}
```

### Serializando coleções e tipos aninhados

```kotlin
@Serializable
data class Endereco(
    val rua: String,
    val cidade: String,
    val estado: String
)

@Serializable
data class Pedido(
    val id: Long,
    val itens: List<String>,
    val endereco: Endereco,
    val tags: Set<String> = emptySet(),
    val metadados: Map<String, String> = emptyMap()
)

fun main() {
    val pedido = Pedido(
        id = 1001,
        itens = listOf("Teclado", "Mouse"),
        endereco = Endereco("Rua A", "São Paulo", "SP"),
        tags = setOf("eletronicos", "informatica"),
        metadados = mapOf("prioridade" to "alta")
    )

    val json = Json { prettyPrint = true }
    println(json.encodeToString(pedido))
}
```

### Polimorfismo com sealed classes

```kotlin
@Serializable
sealed class Notificacao {
    @Serializable
    @SerialName("email")
    data class Email(val destinatario: String, val assunto: String) : Notificacao()

    @Serializable
    @SerialName("push")
    data class Push(val token: String, val titulo: String) : Notificacao()

    @Serializable
    @SerialName("sms")
    data class Sms(val telefone: String, val mensagem: String) : Notificacao()
}

fun main() {
    val notificacoes: List<Notificacao> = listOf(
        Notificacao.Email("ana@email.com", "Bem-vinda"),
        Notificacao.Push("token123", "Nova mensagem"),
        Notificacao.Sms("+5511999999999", "Código: 1234")
    )

    val json = Json { prettyPrint = true }
    val jsonStr = json.encodeToString(notificacoes)
    println(jsonStr)

    // Desserializa com o tipo correto baseado no discriminador
    val desserializado = json.decodeFromString<List<Notificacao>>(jsonStr)
    desserializado.forEach { println(it::class.simpleName) }
}
```

### Serializer customizado

Para tipos que não são controlados por você ou que precisam de formatação especial:

```kotlin
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import java.time.LocalDate

object LocalDateSerializer : KSerializer<LocalDate> {
    override val descriptor: SerialDescriptor =
        PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.STRING)

    override fun serialize(encoder: Encoder, value: LocalDate) {
        encoder.encodeString(value.toString())
    }

    override fun deserialize(decoder: Decoder): LocalDate {
        return LocalDate.parse(decoder.decodeString())
    }
}

@Serializable
data class Evento(
    val nome: String,
    @Serializable(with = LocalDateSerializer::class)
    val data: LocalDate
)
```

### Outros formatos além de JSON

kotlinx.serialization suporta múltiplos formatos:

```kotlin
// Protobuf
implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.6.2")

@Serializable
data class Mensagem(@ProtoNumber(1) val texto: String, @ProtoNumber(2) val id: Int)

val bytes = ProtoBuf.encodeToByteArray(Mensagem("Ola", 1))
val msg = ProtoBuf.decodeFromByteArray<Mensagem>(bytes)

// CBOR
implementation("org.jetbrains.kotlinx:kotlinx-serialization-cbor:1.6.2")

val cborBytes = Cbor.encodeToByteArray(usuario)
```

### Quando usar kotlinx.serialization

- **APIs REST**: serializar e desserializar JSON em chamadas HTTP com Ktor ou Retrofit.
- **Armazenamento local**: salvar dados em arquivos ou bancos de dados em formato JSON.
- **Kotlin Multiplatform**: a única biblioteca de serialização que funciona em todas as plataformas.
- **Performance crítica**: geracao de código em tempo de compilação e mais rápida que reflexao.
- **Comunicação entre serviços**: usar Protobuf ou CBOR para formatos binarios eficientes.

### Casos de Uso no Mundo Real

1. **comunicação com APIs REST**: em aplicações Android e backend com Ktor, kotlinx.serialization e usado para converter respostas JSON de APIs em data classes Kotlin e vice-versa. A integração com Ktor e nativa, dispensando configuração adicional para serialização de requisicoes e respostas.

2. **Armazenamento local estruturado**: aplicações que precisam salvar estado ou configuracoes em disco usam kotlinx.serialization para converter objetos em JSON e gravar em arquivos ou DataStore. Na leitura, os dados sao desserializados de volta para objetos tipados, garantindo type safety.

3. **Kotlin Multiplatform (KMP)**: em projetos multiplataforma que compartilham código entre Android, iOS, web e desktop, kotlinx.serialization e a única biblioteca de serialização que funciona em todos os targets. Modelos de dados compartilhados sao anotados com `@Serializable` uma única vez e funcionam em todas as plataformas.

4. **comunicação entre microsservicos**: backends Kotlin que se comunicam via gRPC ou mensageria (Kafka, RabbitMQ) usam formatos binarios como Protobuf ou CBOR com kotlinx.serialization para obter serialização eficiente e compacta, reduzindo latencia e consumo de banda.

### Boas Praticas

- **Configure `ignoreUnknownKeys = true` ao consumir APIs externas**: APIs de terceiros podem adicionar campos novos a qualquer momento. Sem essa configuração, campos desconhecidos causam exceção e quebram sua aplicação.
- **Use `@SerialName` para desacoplar nomes Kotlin de nomes JSON**: mantenha nomes de propriedades idiomaticos em Kotlin (camelCase) e use `@SerialName` para mapear para o formato da API (snake_case ou outro), evitando dependência direta do formato externo.
- **Crie uma instancia reutilizavel de `Json` com suas configuracoes**: em vez de criar uma nova instancia a cada serialização, defina um objeto `Json` configurado uma vez e reutilize-o em toda a aplicação. Isso melhora performance e garante consistencia.
- **Prefira `encodeDefaults = false` para payloads menores**: quando campos com valor padrão não precisam ser enviados, desativar a codificacao de defaults reduz o tamanho do JSON e o trafego de rede.
- **Valide dados desserializados apos a conversao**: kotlinx.serialization garante que o JSON e válido e que os tipos estao corretos, mas não válida regras de negócio. Adicione validacao explicita (como verificar se um email tem formato válido) apos a desserializacao.

### Perguntas Frequentes

**P: Qual a diferenca entre kotlinx.serialization e Gson/Jackson/Moshi?**
R: kotlinx.serialization gera código de serialização em tempo de compilação, enquanto Gson e Jackson usam reflexao em tempo de execução. Isso torna kotlinx.serialization mais rápida, type-safe e compativel com Kotlin Multiplatform. Alem disso, kotlinx.serialization entende nativamente recursos do Kotlin como valores padrão, nullability e sealed classes.

**P: Posso usar kotlinx.serialization com Retrofit?**
R: Sim. Existe o artefato `com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter` que adiciona suporte a kotlinx.serialization como converter factory do Retrofit. Com Ktor, a integração e nativa e não precisa de converters adicionais.

**P: Como serializo classes que não posso anotar com `@Serializable` (classes de terceiros)?**
R: Voce pode criar um `KSerializer` customizado para o tipo e registra-lo no modulo de serialização usando `SerializersModule`. Outra opção e criar uma classe wrapper ou surrogate anotada com `@Serializable` que represente os mesmos dados.

**P: kotlinx.serialization funciona com tipos genericos?**
R: Sim, mas com uma restricao: você precisa fornecer o serializer explicitamente para tipos genericos, pois o Kotlin não mantém informação de tipo generico em tempo de execução (type erasure). Use `serializer<MeuTipo<Param>>()` ou passe o serializer como parametro.

### Erros comuns

1. **Esquecer a anotacao @Serializable**: sem ela, o plugin não gera o serializer e você recebe um erro em tempo de execução.

2. **Nao aplicar o plugin do compilador**: apenas adicionar a dependência não basta. O plugin `kotlin("plugin.serialization")` deve ser aplicado no build.gradle.kts.

3. **Ignorar campos desconhecidos sem configurar**: por padrão, campos extras no JSON causam exceção. Use `ignoreUnknownKeys = true` quando consumir APIs externas.

4. **Confundir com Gson ou Jackson**: kotlinx.serialization tem API e anotações proprias. Misturar anotações de Gson com kotlinx.serialization não funciona.

5. **Nao tratar nulls e ausentes**: em JSON, um campo pode estar ausente ou ter valor `null`. Configure `explicitNulls` e `coerceInputValues` conforme necessário.

### Termos relacionados

- **JSON**: formato de dados textual amplamente usado em APIs web.
- **Data Class**: tipo ideal para serialização por ter propriedades claras e método `copy`.
- **Sealed Class**: permite serialização polimorfica com discriminador de tipo.
- **KSP**: processamento de simbolos, alternativa ao plugin de compilador para geracao de código.
- **Kotlin Multiplatform**: plataforma onde kotlinx.serialization brilha por funcionar em todos os targets.
- **Gradle Plugin**: o plugin de serialização e aplicado no sistema de build.

kotlinx.serialization e a forma padrão e recomendada de serializar dados em Kotlin. Sua geracao de código em tempo de compilação, suporte multiplataforma e integração com o ecossistema Kotlin fazem dela a escolha natural para qualquer projeto moderno.
