1. Serialización binaria en Java
La serialización binaria es el mecanismo estándar de Java por el que un objeto se transforma en un flujo de bytes de forma lo más compacta y rápida posible. Para ello se usan las clases ObjectOutputStream y ObjectInputStream. El archivo resultante es un conjunto de bytes que no está pensado para ser leído por una persona.
Se llama binaria porque todo se serializa en «estado bruto»: números, cadenas, arrays e incluso las referencias entre objetos se convierten en bytes. Es como una maleta empaquetada a presión: eficiente y rápida, pero sin instrucciones no es obvio qué hay y dónde.
¿Cómo funciona en Java?
Supongamos que tenemos la clase User:
import java.io.Serializable;
public class User implements Serializable {
private String name;
private int age;
// Constructor, getters y setters
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
Serialización a un archivo binario
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
User user = new User("Vasya", 30);
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.bin"))) {
out.writeObject(user);
System.out.println("El objeto User se ha serializado en el archivo user.bin");
} catch (Exception e) {
e.printStackTrace();
}
Deserialización desde un archivo binario
import java.io.FileInputStream;
import java.io.ObjectInputStream;
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.bin"))) {
User loadedUser = (User) in.readObject();
System.out.println("Leído del archivo: " + loadedUser.getName() + ", " + loadedUser.getAge());
} catch (Exception e) {
e.printStackTrace();
}
Atención: si abre el archivo user.bin en un editor de texto, verá algo como: ¬í sr ... — es normal, ¡así está diseñado!
Ventajas de la serialización binaria
- Compacidad y velocidad. El guardado y la lectura se realizan lo más rápido posible, sin «adornos» innecesarios.
- Se guardan todos los campos del objeto, incluidos los objetos anidados (si también son serializables mediante Serializable).
- Fácil de usar para caché interno o para intercambio entre programas Java.
Desventajas
- Ilegibilidad. Una persona no podrá «echar un vistazo» al contenido y entender qué hay dentro.
- Fuerte acoplamiento a la versión de la clase. Cambiar la estructura (añadir/eliminar campos) puede «romper» la lectura de archivos antiguos.
- Problemas de compatibilidad entre diferentes versiones de Java y la JVM.
- No apto para el intercambio con otros lenguajes de programación.
- Seguridad: deserializar datos de fuentes no fiables es un camino directo hacia vulnerabilidades.
2. Formatos de serialización de texto: JSON, XML y otros
La serialización binaria es buena para uso interno, pero a menudo hay que intercambiar datos entre distintos lenguajes (Java, JavaScript, Python) o almacenarlos en un formato legible, lo cual es práctico para configuraciones, logs y API. Para ello se emplean formatos de texto: JSON, XML, YAML, CSV, etc.
JSON: el más popular
JSON (JavaScript Object Notation) es un formato compacto y legible. Ejemplo de un objeto User serializado:
{
"name": "Vasya",
"age": 30
}
En Java, para trabajar con JSON se usan con más frecuencia las bibliotecas: Jackson (la más popular), Gson, y también Moshi, JSON-B, etc.
XML: el viejo amigo del programador
XML (Extensible Markup Language) es más «verboso», pero formal y estricto.
<User>
<name>Vasya</name>
<age>30</age>
</User>
Para XML en Java se suele usar la biblioteca estándar JAXB (o la más antigua XStream).
YAML, CSV y otros
- YAML se parece a JSON, pero es más conciso; se usa más para configuraciones que para serializar objetos complejos.
- CSV es bueno para tablas «planas», pero poco adecuado para estructuras anidadas.
- Hay formatos para todos los gustos, pero en Java lo más habitual es usar JSON y XML.
3. Comparación de formatos: ¿cuándo usar cada uno?
| Formato | Legibilidad | Compacidad | Velocidad | Compatibilidad | Cuándo usarlo |
|---|---|---|---|---|---|
| Binario | No | ++ | ++ | Solo Java | Caché interno, guardado rápido entre JVM |
| JSON | Sí | + | + | Cualquier lenguaje | REST API, intercambio con servicios externos, configuraciones |
| XML | Sí | - | - | Cualquier lenguaje | Integración, esquemas estrictos, sistemas heredados |
- Binario: elija este formato para uso interno cuando no se requiera intercambio con sistemas externos y la máxima performance sea importante.
- JSON: la mejor opción para intercambio con aplicaciones web, clientes móviles y REST API, así como para almacenar configuraciones.
- XML: necesario cuando hay esquemas estrictos e integración con soluciones «corporativas».
¡Importante! La serialización binaria es adecuada solo para transferir datos entre programas Java, y aun así es más seguro usarla entre programas de la misma versión. Los formatos de texto como JSON y XML son más universales: sirven para el intercambio de datos entre distintos lenguajes y plataformas, haciendo la información legible y portátil.
4. Práctica: serialización en formato binario y de texto
Serialización binaria (ObjectOutputStream/ObjectInputStream)
Ya lo vimos arriba, pero lo repetimos para afianzar:
// Serialización
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.bin"))) {
out.writeObject(user);
}
// Deserialización
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.bin"))) {
User loadedUser = (User) in.readObject();
}
Serialización a JSON con Jackson (breve)
Para trabajar con Jackson hay que añadir sus bibliotecas al proyecto. Más adelante estudiaremos Maven y Gradle, pero por ahora puede incluir los archivos JAR manualmente. Ejemplo de dependencia para Maven:
<!-- Maven -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
Ejemplo de serialización/deserialización:
import com.fasterxml.jackson.databind.ObjectMapper;
User user = new User("Vasya", 30);
ObjectMapper mapper = new ObjectMapper();
try {
// Serialización a cadena
String json = mapper.writeValueAsString(user);
System.out.println(json); // {"name":"Vasya","age":30}
// Serialización a archivo
mapper.writeValue(new File("user.json"), user);
// Deserialización desde cadena
User loadedUser = mapper.readValue(json, User.class);
// Deserialización desde archivo
User loadedFromFile = mapper.readValue(new File("user.json"), User.class);
} catch (Exception e) {
e.printStackTrace();
}
El archivo JSON se puede abrir en cualquier editor de texto, lo que hace que los datos sean fácilmente legibles y portables entre distintas aplicaciones y lenguajes.
5. Cuándo usar cada formato: consejos prácticos
- Caché interno, archivos temporales, escritura/lectura rápida entre programas Java: use la serialización binaria estándar. ¡Pero recuerde la compatibilidad de versiones!
- Intercambio con servicios externos, almacenamiento de configuraciones, integración con el frontend: use JSON (Jackson, Gson).
- Integración con sistemas «corporativos» donde se requiere un esquema estricto: XML (JAXB).
- Necesita que una persona pueda abrir y leer el archivo: JSON o XML, pero no formato binario.
6. Errores típicos al trabajar con formatos de serialización
Error n.º 1: Intentar serializar un objeto con campos no serializables. Si su clase tiene un campo que no implementa Serializable (por ejemplo, un flujo o una conexión con la BD), la serialización binaria dará un error. Para JSON no es tan crítico, pero con tipos «no estándar» también puede haber problemas.
Error n.º 2: Abrir un archivo binario en un editor de texto y asustarse. ¡Es normal! Los archivos binarios no están pensados para ser leídos por personas.
Error n.º 3: Cambiar la estructura de la clase y que los archivos binarios antiguos dejen de leerse. La serialización binaria es sensible a los cambios en la estructura de la clase: a menudo aparece InvalidClassException. En JSON/XML es menos crítico: los campos desconocidos suelen ignorarse o reciben valores por defecto.
Error n.º 4: Usar la serialización binaria para el intercambio con sistemas externos. No funcionará: el formato binario solo lo entiende Java, y aun así cuando coinciden las versiones.
Error n.º 5: Olvidar añadir las anotaciones necesarias para JSON/XML. Algunas bibliotecas requieren anotaciones como @JsonProperty, @XmlElement; de lo contrario, la serialización/deserialización puede no funcionar como se espera.
Error n.º 6: No comprobar que todos los objetos anidados sean serializables. En la serialización binaria es un problema frecuente; en JSON también, si en el modelo aparecen tipos complejos.
GO TO FULL VERSION