1. Introducción
En muchos libros y ejemplos antiguos de C# puedes encontrar serialización usando la clase BinaryFormatter. En su momento fue el estándar: cómodo, rápido, menos preocupaciones. Un ejemplo de la época se veía más o menos así:
// ¡Código antiguo y peligroso! No hagas esto en proyectos nuevos.
var bf = new BinaryFormatter();
using (var stream = File.Open("player.dat", FileMode.Create))
{
bf.Serialize(stream, playerObject);
}
Pero en el .NET 9 moderno ya ni siquiera podrás compilar ese código: BinaryFormatter fue eliminado de la plataforma.
De héroe a paria
Al principio BinaryFormatter se diseñó como un mecanismo universal para serializar y deserializar objetos .NET, capaz de guardar grafos complejos de objetos “tal cual”. Con el tiempo surgieron problemas serios de seguridad y compatibilidad, y ahora pertenece al pasado — como las cintas de casete en la era del streaming.
2. Principales razones para abandonar BinaryFormatter
Un agujero enorme de seguridad
BinaryFormatter no solo serializa datos, sino que puede reconstruir tipos desde el flujo de entrada. Si deserializas sin pensar datos no verificados (por ejemplo, recibidos por la red), un atacante puede inyectar una carga útil que lleve a ejecución remota de código (RCE). Por eso Microsoft durante años advirtió: «No uses BinaryFormatter». Desde .NET 5 fue marcado como obsoleto y peligroso ([Obsolete]), y en .NET 9 — eliminado.
Dependencia de la estructura interna de las clases
El formato de BinaryFormatter arrastra detalles de implementación de los tipos: campos, empaquetado, versiones. El más mínimo cambio en las clases (añadir/eliminar un campo) rompe la compatibilidad con archivos ya guardados. Eso hace que el formato no sea adecuado para almacenamiento a largo plazo ni intercambio entre versiones.
Problemas de cross-platform
Los datos guardados por BinaryFormatter están ligados a la representación interna de objetos .NET. Leerlos en otra plataforma/lenguaje o incluso en otra versión de .NET suele ser imposible.
3. ¿Cómo detectar «código antiguo» y qué hacer?
Los signos de uso de BinaryFormatter se ven así:
using System.Runtime.Serialization.Formatters.Binary; // <-- ¡sospechoso!
BinaryFormatter bf = new BinaryFormatter(); // <-- ¡peligroso!
bf.Serialize(...);
bf.Deserialize(...);
En versiones modernas de .NET ese código no compila: las herramientas mostrarán un error "Tipo o nombre no encontrado". En proyectos legacy sobre .NET Framework — al menos advertencias severas.
Si te encuentras con ese código, reemplaza BinaryFormatter por alternativas modernas y seguras.
¿Qué formatos y clases usar hoy?
Para JSON
- System.Text.Json — rápido, seguro, integrado en .NET. Documentación oficial
- Newtonsoft.Json — biblioteca externa popular para casos complejos.
Para XML
- XmlSerializer — serialización a XML. Documentación
Para formatos binarios
- System.Formats.Cbor (CBOR)
- Protobuf.Net (Protocol Buffers), MessagePack for C#
Para tareas específicas elige formatos y librerías especializadas — ya no existe un serializador binario “universal” al estilo de BinaryFormatter, y eso es bueno.
4. Reescribiendo código desde BinaryFormatter
Para qué no usar BinaryFormatter
No debes:
- Guardar configuraciones de usuario y datos importantes.
- Transmitir datos por la red (cliente ↔ servidor).
- Deserializar datos de orígenes no verificados.
En su lugar:
- Para necesidades diarias — System.Text.Json.
- Para configuraciones — JSON, XML, etc.
- Para intercambio entre lenguajes — formatos con compatibilidad cross-platform (JSON, XML, Protobuf, MessagePack).
¿Qué código escribir ahora?
Serialización a JSON (método recomendado)
using System.Text.Json;
// Tu clase:
public class Player
{
public string Name { get; set; } = "";
public int Health { get; set; }
public bool IsAlive { get; set; }
}
// Objeto para serializar
var player = new Player { Name = "Aragorn", Health = 100, IsAlive = true };
// Convertimos el objeto a una cadena JSON
string json = JsonSerializer.Serialize(player);
// Guardamos en un archivo — ¡seguro!
File.WriteAllText("player.json", json);
// Para restaurar el objeto desde el archivo:
string loadedJson = File.ReadAllText("player.json");
Player loadedPlayer = JsonSerializer.Deserialize<Player>(loadedJson)!;
Serialización a XML (si necesitas un formato estricto)
using System.Xml.Serialization;
// La clase debe tener un constructor público sin parámetros
var player = new Player { Name = "Aragorn", Health = 100, IsAlive = true };
var serializer = new XmlSerializer(typeof(Player));
using (var fs = File.Create("player.xml"))
{
serializer.Serialize(fs, player);
}
Esquema visual «antiguo vs nuevo»
| Tarea | Método antiguo (BinaryFormatter) | Método moderno |
|---|---|---|
| Serializar a archivo | |
|
| Deserializar desde archivo | |
|
| Seguridad | Vulnerable a ataques (RCE) | Parsers seguros y modelos estrictos |
| Cross-platform | No | Sí (JSON/XML/Protobuf) |
| Velocidad | Rápido, pero peligroso | Rápido y seguro |
5. Errores típicos al trabajar con XmlSerializer
Error nº1: propiedades o campos privados. XmlSerializer serializa solo propiedades public; incluso protected provocará error.
Error nº2: ausencia de constructor por defecto. Se necesita un constructor público sin parámetros, si no la serialización/deserialización fallará.
Error nº3: discrepancia entre tipos de datos. XmlSerializer funciona mal con Dictionary, interface y delegate — usa wrappers u otros formatos.
Error nº4: referencias cíclicas (circular reference). XmlSerializer no soporta grafos tipo A → B → A; para esos casos suele usarse JSON con configuraciones adecuadas.
GO TO FULL VERSION