La serialización y deserialización son procesos fundamentales de conversión de objetos en un formato para su transmisión o almacenamiento. En el desarrollo móvil, estos mecanismos se utilizan en cada solicitud de red, guardado de estado y comunicación entre procesos. Según MDN Web Docs, 2024, JSON sigue siendo el formato más popular de serialización en la web y aplicaciones móviles, superando a XML y Protocol Buffers.
Puntos clave
La serialización es el proceso de convertir un objeto de aplicación en un formato adecuado para su transmisión por red o almacenamiento en disco. La deserialización realiza la conversión inversa, restaurando el objeto a partir de los datos recibidos. En el desarrollo móvil, la serialización se utiliza en solicitudes API, guardado de estado de pantalla, almacenamiento en caché y transferencia de datos a través de Intent o Bundle.
Cualquier interacción entre componentes de la aplicación o entre la aplicación y el servidor requiere serialización. Las API REST transmiten datos en JSON o XML, gRPC utiliza Protocol Buffers y la comunicación intraproceso en Android usa Parcelable. Sin serialización, es imposible transferir un objeto complejo a través del límite de un proceso o guardarlo en una base de datos.
// Principio general de serialización
data class User(
val id: Int,
val name: String,
val email: String
)
// Serialización: objeto -> JSON
fun serializeUser(user: User): String {
return """{"id":${user.id},"name":"${user.name}","email":"${user.email}"}"""
}
// Deserialización: JSON -> objeto
fun deserializeUser(json: String): User? {
// análisis de JSON a objeto
return Gson().fromJson(json, User::class.java)
}
| Formato | Tamaño | Velocidad | Legibilidad | Tipificación |
|---|---|---|---|---|
| JSON | medio | alta | alta | dinámica |
| XML | grande | media | alta | esquema XSD |
| Protocol Buffers | pequeño | muy alta | baja | estricta .proto |
| FlatBuffers | pequeño | máxima | baja | estricta .fbs |
JSON (JavaScript Object Notation) es un formato de texto ligero basado en la sintaxis de objetos de JavaScript. JSON admite cadenas, números, valores booleanos, matrices y objetos anidados, cubriendo la mayoría de los escenarios de transferencia de datos en aplicaciones móviles. El formato es independiente de la plataforma: cada ecosistema proporciona herramientas integradas para su análisis.
JSON gana por su simplicidad y versatilidad. El desarrollador no necesita un esquema para uso básico: la estructura se determina dinámicamente durante el análisis. La legibilidad del formato simplifica la depuración y las pruebas: la respuesta del servidor se puede ver en cualquier herramienta de desarrollador. En ambas plataformas móviles, JSON se procesa de forma nativa sin necesidad de bibliotecas de terceros.
// Codable — serialización JSON nativa en 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) es un formato de serialización binario desarrollado por Google para sistemas de alto rendimiento. A diferencia de JSON, protobuf requiere un esquema predefinido en un archivo .proto, pero proporciona un tamaño de datos significativamente menor y una mayor velocidad de procesamiento. El formato se utiliza en gRPC, Firebase Firestore y servicios internos de Google.
Un esquema protobuf describe mensajes con campos tipificados, cada uno con un número único. El compilador protoc genera clases en el lenguaje de destino que realizan la serialización y deserialización automáticamente. Protobuf admite la evolución del esquema mediante reglas para agregar y eliminar campos sin perder la compatibilidad hacia atrás.
// Definición de esquema en user.proto
syntax = "proto3";
message User {
int32 id = 1;
string name = 2;
string email = 3;
repeated string roles = 4;
}
// Código generado en Kotlin
val user = UserProto.User.newBuilder()
.setId(1)
.setName("John")
.setEmail("john@test.com")
.build()
val bytes: ByteArray = user.toByteArray()
XML (eXtensible Markup Language) es un formato con estructura rígida, soporte de espacios de nombres y validación mediante esquemas XSD. XML pierde frente a JSON en compacidad y velocidad de análisis, pero sigue siendo demandado en el desarrollo de Android para archivos de diseño, AndroidManifest, recursos y configuraciones de Gradle. En iOS, XML se utiliza en archivos plist y algunos servicios heredados.
Android ofrece tres enfoques para el análisis de XML: DOM (carga de todo el documento en memoria), SAX (análisis de flujo basado en eventos) y XmlPullParser (un enfoque híbrido). XmlPullParser es la opción recomendada para dispositivos móviles, ya que funciona de manera eficiente con memoria limitada y permite procesar el documento a medida que se lee.
// XmlPullParser en 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 ofrece sus propias herramientas de serialización. En iOS, el mecanismo principal es el protocolo Codable con JSONEncoder y JSONDecoder, mientras que Objective-C usa NSJSONSerialization. Android utiliza las bibliotecas Gson, Moshi y kotlinx.serialization. Para la transferencia de datos entre procesos, Android emplea Parcelable, mientras que iOS usa NSKeyedArchiver. Los proyectos Kotlin eligen cada vez más kotlinx.serialization, una solución de JetBrains que admite multiplataforma y no depende de la reflexión, generando serializadores en tiempo de compilación a través del complemento del compilador de Kotlin.
Android admite dos mecanismos de serialización para Intent y Bundle. Serializable es un mecanismo estándar de Java que utiliza reflexión, lo que conduce a un rendimiento inferior. Parcelable es un protocolo específico de Android que requiere la implementación manual de los métodos writeToParcel y createFromParcel, pero funciona decenas de veces más rápido gracias a la manipulación directa de bytes.
// Parcelable en Android
@Parcelize
data class UserParcel(
val id: Int,
val name: String,
val email: String
) : Parcelable
// Transferencia a través de Intent
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("user", userParcel)
startActivity(intent)
En iOS, Codable con serialización preliminar en Data se utiliza para la transferencia de datos entre controladores, mientras que NSKeyedArchiver se usa para la comunicación entre procesos, convirtiendo objetos al formato binario Property List. Los proyectos modernos de SwiftUI prefieren codificar datos a través de JSONEncoder para transferirlos entre módulos de la aplicación.
La deserialización incorrecta de datos no confiables puede provocar vulnerabilidades. Los ataques a través de la serialización explotan métodos readObject sobrescritos en Java o deserializadores inseguros de bibliotecas de terceros. En Android, se debe evitar Serializable para datos de fuentes no confiables, usando Parcelable o validación manual de todos los campos después de la deserialización. En iOS, JSONDecoder es estricto por defecto con los tipos, pero al trabajar con JSONSerialization, los desarrolladores deben verificar los tipos mediante conversión condicional.
Al elegir un formato de serialización, se consideran los requisitos de rendimiento, el tamaño de los datos y la compatibilidad. Para API REST y arquitectura de microservicios, JSON sigue siendo la opción óptima: es compatible con todas las plataformas y lenguajes. Para sistemas de alta carga y aplicaciones móviles con ancho de banda limitado, son preferibles Protocol Buffers, que ofrecen un tamaño más pequeño y una deserialización más rápida. XML solo se justifica en escenarios de configuración y al integrarse con sistemas heredados. Los proyectos modernos también están viendo el auge de FlatBuffers, un formato binario sin etapa de deserialización, utilizado en motores de juegos y aplicaciones con latencia mínima. Cada formato tiene su nicho, y la elección correcta afecta directamente la velocidad de la aplicación y el volumen de tráfico consumido.
Preguntas frecuentes
La serialización es el empaquetado de un objeto de aplicación en un formato que se puede enviar a través de una red o guardar en un archivo. Imagine que toma una foto de un objeto: la foto es la serialización y restaurar el objeto a partir de la foto es la deserialización.
JSON es un formato de texto legible por humanos que no requiere un esquema. Protocol Buffers es un formato binario con un esquema obligatorio (.proto), tamaño significativamente menor y mayor velocidad. Protobuf se elige para sistemas de alta carga, mientras que JSON se elige para compatibilidad universal.
XML sigue siendo el estándar para archivos de configuración (AndroidManifest, recursos de diseño), documentos con anidación compleja y sistemas con validación estricta mediante XSD. XML también se utiliza en protocolos SOAP y sistemas heredados que requieren soporte de espacios de nombres.
Codable es un protocolo de Swift que combina Encodable y Decodable para la serialización y deserialización automáticas. El compilador genera la implementación de los métodos encode(to:) e init(from:) para todas las propiedades de la estructura o clase.
Parcelable funciona significativamente más rápido que Serializable porque no utiliza reflexión y escribe campos directamente en un flujo de bytes. En dispositivos modernos, la diferencia puede alcanzar una aceleración de 10 veces a favor de Parcelable.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también