Serialização e desserialização são processos fundamentais de conversão de objetos em um formato para transmissão ou armazenamento. No desenvolvimento móvel, esses mecanismos são usados em cada requisição de rede, salvamento de estado e comunicação entre processos. De acordo com MDN Web Docs, 2024, JSON continua sendo o formato mais popular de serialização na web e em aplicações móveis, superando XML e Protocol Buffers.
Principais conclusões
Serialização é o processo de converter um objeto de aplicação em um formato adequado para transmissão em rede ou armazenamento em disco. A desserialização realiza a conversão inversa, restaurando o objeto a partir dos dados recebidos. No desenvolvimento móvel, a serialização é usada em requisições de API, salvamento de estado de tela, cache e transferência de dados via Intent ou Bundle.
Qualquer interação entre componentes da aplicação ou entre a aplicação e o servidor requer serialização. APIs REST transmitem dados em JSON ou XML, gRPC usa Protocol Buffers e a comunicação intraprocesso no Android usa Parcelable. Sem serialização, é impossível passar um objeto complexo através do limite de um processo ou salvá-lo em um banco de dados.
// Princípio geral de serialização
data class User(
val id: Int,
val name: String,
val email: String
)
// Serialização: objeto -> JSON
fun serializeUser(user: User): String {
return """{"id":${user.id},"name":"${user.name}","email":"${user.email}"}"""
}
// Desserialização: JSON -> objeto
fun deserializeUser(json: String): User? {
// análise de JSON para objeto
return Gson().fromJson(json, User::class.java)
}
| Formato | Tamanho | Velocidade | Legibilidade | Tipagem |
|---|---|---|---|---|
| JSON | médio | alta | alta | dinâmica |
| XML | grande | média | alta | esquema XSD |
| Protocol Buffers | pequeno | muito alta | baixa | estrita .proto |
| FlatBuffers | pequeno | máxima | baixa | estrita .fbs |
JSON (JavaScript Object Notation) é um formato de texto leve baseado na sintaxe de objetos JavaScript. JSON suporta strings, números, valores booleanos, arrays e objetos aninhados, cobrindo a maioria dos cenários de transferência de dados em aplicações móveis. O formato é independente de plataforma: cada ecossistema fornece ferramentas integradas para sua análise.
JSON vence pela sua simplicidade e versatilidade. O desenvolvedor não precisa de um esquema para uso básico — a estrutura é determinada dinamicamente durante a análise. A legibilidade do formato simplifica a depuração e os testes: a resposta do servidor pode ser visualizada em qualquer ferramenta de desenvolvedor. Em ambas as plataformas móveis, o JSON é processado nativamente sem a necessidade de bibliotecas de terceiros.
// Codable — serialização JSON nativa em Swift
struct User: Codable {
let id: Int
let name: String
let email: String
}
let jsonString = """{"id":1,"name":"John","email":"john@test.com"}"""
let jsonData = Data(jsonString.utf8)
let decoder = JSONDecoder()
let user = try! decoder.decode(User.self, from: jsonData)
Protocol Buffers (protobuf) é um formato de serialização binário desenvolvido pelo Google para sistemas de alto desempenho. Ao contrário do JSON, o protobuf requer um esquema predefinido em um arquivo .proto, mas fornece um tamanho de dados significativamente menor e maior velocidade de processamento. O formato é usado em gRPC, Firebase Firestore e serviços internos do Google.
Um esquema protobuf descreve mensagens com campos tipados, cada um com um número único. O compilador protoc gera classes na linguagem alvo que realizam serialização e desserialização automaticamente. O Protobuf suporta evolução de esquema através de regras para adicionar e remover campos sem perder a compatibilidade reversa.
// Definição de esquema em user.proto
syntax = "proto3";
message User {
int32 id = 1;
string name = 2;
string email = 3;
repeated string roles = 4;
}
// Código gerado em Kotlin
val user = UserProto.User.newBuilder()
.setId(1)
.setName("John")
.setEmail("john@test.com")
.build()
val bytes: ByteArray = user.toByteArray()
XML (eXtensible Markup Language) é um formato com estrutura rígida, suporte a namespaces e validação através de esquemas XSD. XML perde para JSON em compacidade e velocidade de análise, mas continua sendo demandado no desenvolvimento Android para arquivos de layout, AndroidManifest, recursos e configurações do Gradle. No iOS, XML é usado em arquivos plist e alguns serviços legados.
O Android oferece três abordagens para análise de XML: DOM (carregamento de todo o documento na memória), SAX (análise de fluxo orientada a eventos) e XmlPullParser (uma abordagem híbrida). XmlPullParser é a opção recomendada para dispositivos móveis, pois funciona eficientemente com memória limitada e permite processar o documento à medida que é lido.
// XmlPullParser no Android
fun parseUserXml(inputStream: InputStream): User? {
val parser = Xml.newPullParser()
parser.setInput(inputStream, Xml.Encoding.UTF_8.name)
var id: Int? = null
var name: String? = null
var email: String? = null
while (parser.next() != XmlPullParser.END_DOCUMENT) {
if (parser.eventType == XmlPullParser.START_TAG
&& parser.name == "email") {
email = parser.nextText()
}
}
return User(id!!, name!!, email!!)
}
Cada plataforma oferece suas próprias ferramentas de serialização. No iOS, o mecanismo principal é o protocolo Codable com JSONEncoder e JSONDecoder, enquanto Objective-C usa NSJSONSerialization. O Android usa as bibliotecas Gson, Moshi e kotlinx.serialization. Para transferência de dados entre processos, o Android emprega Parcelable, enquanto o iOS usa NSKeyedArchiver. Projetos Kotlin escolhem cada vez mais kotlinx.serialization — uma solução da JetBrains que suporta multiplataforma e não depende de reflexão, gerando serializadores em tempo de compilação através do plugin do compilador Kotlin.
O Android suporta dois mecanismos de serialização para Intent e Bundle. Serializable é um mecanismo Java padrão que usa reflexão, levando a um desempenho inferior. Parcelable é um protocolo específico do Android que requer implementação manual dos métodos writeToParcel e createFromParcel, mas funciona dezenas de vezes mais rápido devido à manipulação direta de bytes.
// Parcelable no Android
@Parcelize
data class UserParcel(
val id: Int,
val name: String,
val email: String
) : Parcelable
// Transferência via Intent
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("user", userParcel)
startActivity(intent)
No iOS, Codable com serialização preliminar em Data é usado para transferência de dados entre controladores, enquanto NSKeyedArchiver é usado para comunicação entre processos, convertendo objetos no formato binário Property List. Projetos modernos em SwiftUI preferem codificar dados através de JSONEncoder para transferência entre módulos da aplicação.
A desserialização incorreta de dados não confiáveis pode levar a vulnerabilidades. Ataques através de serialização exploram métodos readObject sobrescritos em Java ou desserializadores inseguros de bibliotecas de terceiros. No Android, deve-se evitar Serializable para dados de fontes não confiáveis, usando Parcelable ou validação manual de todos os campos após a desserialização. No iOS, JSONDecoder é estrito por padrão com tipos, mas ao trabalhar com JSONSerialization, os desenvolvedores devem verificar os tipos através de conversão condicional.
Ao escolher um formato de serialização, são considerados os requisitos de desempenho, tamanho dos dados e compatibilidade. Para APIs REST e arquitetura de microsserviços, JSON continua sendo a escolha ideal — é suportado por todas as plataformas e linguagens. Para sistemas de alta carga e aplicações móveis com largura de banda limitada, Protocol Buffers são preferíveis, oferecendo tamanho menor e desserialização mais rápida. XML é justificado apenas em cenários de configuração e ao integrar com sistemas legados. Projetos modernos também estão vendo o aumento do FlatBuffers — um formato binário sem etapa de desserialização, usado em engines de jogos e aplicações com latência mínima. Cada formato tem seu nicho, e a escolha correta afeta diretamente a velocidade da aplicação e o volume de tráfego consumido.
Perguntas frequentes
Serialização é o empacotamento de um objeto de aplicação em um formato que pode ser enviado através de uma rede ou salvo em um arquivo. Imagine que você tira uma foto de um objeto — a foto é a serialização, e restaurar o objeto a partir da foto é a desserialização.
JSON é um formato de texto legível por humanos que não requer um esquema. Protocol Buffers é um formato binário com um esquema obrigatório (.proto), tamanho significativamente menor e maior velocidade. Protobuf é escolhido para sistemas de alta carga, enquanto JSON é escolhido para compatibilidade universal.
XML continua sendo o padrão para arquivos de configuração (AndroidManifest, recursos de layout), documentos com aninhamento complexo e sistemas com validação estrita via XSD. XML também é usado em protocolos SOAP e sistemas legados que exigem suporte a namespaces.
Codable é um protocolo Swift que combina Encodable e Decodable para serialização e desserialização automáticas. O compilador gera a implementação dos métodos encode(to:) e init(from:) para todas as propriedades da estrutura ou classe.
Parcelable funciona significativamente mais rápido que Serializable porque não usa reflexão e escreve campos diretamente em um fluxo de bytes. Em dispositivos modernos, a diferença pode chegar a uma aceleração de 10 vezes a favor do Parcelable.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também