1. Introducción
Ya estamos acostumbrados a crear objetos en nuestros programas. Recuerda, pronto empezaremos a profundizar en clases y objetos, pero ya ahora entendemos que variables, listas, incluso cadenas simples — no son cualquier cosa, son entidades en nuestro programa. Por ejemplo, podemos crear una variable int age = 30; o string name = "Vasya";. Pero, ¿y si necesitamos guardar en un archivo la información de todo un usuario, que tiene nombre, edad, dirección, una lista de libros favoritos y mucho más?
Imagina: estás haciendo un juego. Tienes un objeto Player con un montón de características: salud, nivel, inventario (lista de items), coordenadas en el mapa, etc. El jugador juega, sube de nivel, encuentra artefactos chulos. Y de repente decide salir del juego. ¿Qué pasará? ¡Todos los datos de sus aventuras que estaban en memoria desaparecerán! ¡Qué triste! Para que eso no pase, necesitamos guardar el estado del objeto Player en un archivo, y cuando el jugador vuelva, cargarlo de nuevo.
Aquí entra en escena la serialización. Es justamente lo que crea un puente entre los objetos "vivos" en memoria y los datos "muertos", pero persistentes, en el disco.
2. Proceso de serialización (de objeto a archivo)
Vamos a desglosar cómo ocurre esta "magia" de convertir un objeto en bytes que se pueden escribir en un archivo.
Imagina que tenemos esta clase Book (Libro):
// Este es nuestro "plano" o "diseño" para crear objetos-book
public class Book
{
// Propiedades del libro
public string Title { get; set; } // Título del libro
public string Author { get; set; } // Autor
public int Year { get; set; } // Año de publicación
// Constructor - método especial para crear nuevos objetos Book
public Book(string title, string author, int year)
{
Title = title;
Author = author;
Year = year;
}
// Método para mostrar info del libro (por ahora no obligatorio para serialización, pero útil)
public void DisplayInfo()
{
Console.WriteLine($"Título: {Title}, Autor: {Author}, Año: {Year}");
}
}
Paso 1: Crear el objeto para serializar.
Primero necesitamos el objeto que queramos guardar. Por ejemplo, creamos una instancia de Book:
Book myFavoriteBook = new Book("Autoestop por la Galaxia", "Douglas Adams", 1979);
Este objeto myFavoriteBook ahora mismo está en la memoria RAM.
Paso 2: Elegir la herramienta (serializador).
No podemos simplemente "copiar" el objeto al disco. El ordenador no entiende objetos directamente en archivos — necesita bytes. Hace falta una herramienta especial — el serializador. Su trabajo es descomponer el objeto en partes (sus propiedades: Title, Author, Year) y convertir esas partes en una secuencia de bytes o en una cadena de texto (por ejemplo, JSON o XML).
No vamos a profundizar hoy en implementaciones concretas — solo mantener en mente que es una "caja-conversora" especial.
Paso 3: Convertir el objeto en un flujo de datos.
El serializador toma nuestro objeto myFavoriteBook, mira sus propiedades (Title, Author, Year) y transforma cada una en un formato que se pueda escribir. Todos esos bytes (o caracteres de texto) se unen en un único flujo de datos — una "cinta" larga de información.
Paso 4: Escribir el flujo en un archivo.
Ahora que tenemos esa "cinta de bytes", usamos nuestros conocidos FileStream y, si hace falta, StreamWriter (si elegimos un formato de texto como JSON) o solo FileStream (para datos binarios puros), para escribir ese flujo en el disco.
3. Proceso de deserialización (de archivo a objeto)
Paso 1: Leer el flujo de datos desde el archivo.
De nuevo usamos FileStream y si hace falta StreamReader (si es un formato de texto), para leer el contenido del archivo. Los datos llegan como una "cinta" de bytes o texto.
Paso 2: Elegir la herramienta (deserializador).
Hace falta la herramienta inversa — el deserializador. Debe saber interpretar los bytes/texto recibidos y reconstruir correctamente la estructura del objeto. Es muy importante: para deserializar se suele usar el mismo tipo de serializador (y normalmente la misma librería) que se usó para serializar; si no, tu "constructor" no entenderá las instrucciones de ensamblaje.
Paso 3: Convertir el flujo de vuelta en un objeto.
El deserializador lee los datos, entiende dónde está Title, luego Author, luego Year, y con esa info crea un nuevo objeto Book en memoria, llenando sus propiedades.
Paso 4: Obtener el objeto listo.
¡Voilà! De nuevo tenemos un objeto completo Book en RAM, con el que podemos trabajar.
Ejemplo: Guardamos nuestro "Súper-Libro" "a mano" (para entender la idea)
Por ahora no usaremos librerías especializadas: haremos la serialización y deserialización más simple "a mano" con StreamWriter y StreamReader. Esto ayuda a entender el principio.
Nuestro objeto Book:
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
public int Year { get; set; }
public Book(string title, string author, int year)
{
Title = title;
Author = author;
Year = year;
}
public void DisplayInfo()
{
Console.WriteLine($"Título: \"{Title}\", Autor: {Author}, Año: {Year}");
}
}
Serialización manual: método SaveBookToTextFile
Crearemos un método que guarde las propiedades del libro en un archivo de texto, una propiedad por línea.
void SaveBookToTextFile(Book book, string filePath)
{
using var writer = new StreamWriter(filePath);
writer.WriteLine(book.Title);
writer.WriteLine(book.Author);
writer.WriteLine(book.Year);
}
¿Qué pasa aquí? Abrimos un StreamWriter y escribimos secuencialmente Title, Author, Year — ese es nuestro esquema de serialización más simple.
Si ejecutas el código, el contenido del archivo será así:
Autoestop por la Galaxia
Douglas Adams
1979
Deserialización manual: método LoadBookFromTextFile
Escribimos un método que lea los datos y construya un nuevo objeto Book.
Book LoadBookFromTextFile(string filePath)
{
using var reader = new StreamReader(filePath);
string title = reader.ReadLine();
string author = reader.ReadLine();
int year = int.Parse(reader.ReadLine());
return new Book(title, author, year);
}
Y usamos estos métodos en Main:
//creamos el objeto
var myBook = new Book("Autoestop por la Galaxia", "Douglas Adams", 1979);
string filePath = "my_favorite_book.txt";
//lo guardamos en archivo
SaveBookToTextFile(myBook, filePath);
//leemos desde el archivo
Book loadedBook = LoadBookFromTextFile(filePath);
¿Qué pasa en LoadBookFromTextFile? Abrimos un StreamReader y en el mismo orden leemos las líneas: primero el título, luego el autor, luego el año y lo convertimos con int.Parse. Después creamos una nueva instancia de Book.
En la práctica conviene añadir comprobaciones (File.Exists) y manejo de errores con try-catch, pero aquí nos centramos en la idea principal.
¿Por qué la serialización "manual" es mala (y por qué hacen falta librerías)?
- Mucho código manual. Cada propiedad hay que escribirla y luego leerla. Si hay muchos objetos y campos — el código crece mucho.
- Fragilidad ante cambios. ¿Añades una nueva propiedad Pages (int)? Tendrás que cambiar la escritura y la lectura, y vigilar el orden estrictamente.
- Estructuras complejas. Colecciones anidadas y objetos (por ejemplo, List<Chapter>) convertirán el código en un "espagueti".
- Formatos y eficiencia. El formato de texto es sencillo, pero no siempre compacto ni seguro; para datos binarios tendrás que trabajar manualmente con bytes, BinaryWriter/BinaryReader, etc.
- No hay metadatos. Nuestro archivo no "sabe" que la primera línea es Title y la tercera es Year. Los serializadores especializados pueden guardar metadatos y ser más resistentes a cambios en los modelos.
Por eso en proyectos reales se usan librerías-serializadoras que pueden analizar/armar objetos automáticamente, trabajar con JSON, XML y formatos binarios, y manejar cambios en los modelos de forma más robusta. ¡De eso hablaremos en la siguiente lección!
Aplicaciones prácticas: ¿para qué sirve la serialización?
- Guardar y cargar datos. Ajustes, estados de juegos, configuraciones.
- Transferencia de datos por la red. Intercambio de objetos complejos entre servicios (a menudo en JSON).
- Cacheo. Reutilizar rápidamente datos obtenidos anteriormente.
- Logueo de objetos complejos. Útil para debugging y auditoría.
- Copia profunda de objetos. Serialización + deserialización como forma de clonar un grafo de objetos.
La serialización es uno de los pilares del software moderno: desde guardar el progreso en un juego hasta trabajar con servicios web — está en todas partes.
GO TO FULL VERSION