1. Introduzione
Dal momento che abbiamo deciso di «smontare il figurino LEGO pezzo per pezzo», capiamo quali strumenti abbiamo a disposizione in .NET. In altre parole — quali classi standard aiutano a serializzare e deserializzare oggetti in vari formati e cosa c'è dietro ciascuna di esse.
Com'è strutturata la famiglia di serializzazione .NET
Alla data attuale (2025) .NET offre diversi approcci principali alla serializzazione, ognuno con il proprio set di classi e strumenti. I principali e più comuni sono:
- JSON-serialization — l'opzione principale e più moderna, usata nella maggior parte dei progetti.
- XML-serialization — un po' più vecchio stile, ma ancora molto usato.
- Binary serialization — solo per casi particolari e normalmente tramite soluzioni esterne moderne.
Molti esempi e la maggior parte del codice in .NET 9 usano proprio il JSON, e non è una moda — è lo standard industriale. Ma .NET supporta anche altri metodi — per ogni evenienza.
I protagonisti della serializzazione .NET
| Formato | Classe di serializzazione | Semplicità | Performance | Sicurezza | Aggiornamento |
|---|---|---|---|---|---|
| JSON | |
🔥🔥🔥 | 🔥🔥🔥 | 🔥🔥🔥 | La più attuale |
| XML | |
🔥🔥 | 🔥🔥 | 🔥🔥 | Usata |
| JSON | Newtonsoft.Json (Json.NET) | 🔥🔥🔥 | 🔥🔥 | 🔥🔥🔥 | Molto popolare |
Breve su ciascuno
- System.Text.Json: il nuovo standard per la serializzazione JSON in .NET, introdotto in .NET Core 3.0, diventato principale in .NET 5+. Veloce, leggero, sicuro, incluso “out of the box” in .NET 9. Documentazione
- XmlSerializer: la vecchia e collaudata opzione per serializzare in XML. Facile da usare, ma con limitazioni (per esempio, richiede una classe public e proprietà pubbliche). Buona per compatibilità e contratti di dati stringenti. Documentazione
- Newtonsoft.Json: per molto tempo è stato lo standard de-facto per la serializzazione JSON prima di System.Text.Json. Spesso usato per scenari complessi (dynamics, proprietà private, ecc.). Documentazione
Dove è finito BinaryFormatter?
Se trovi online consigli di usare BinaryFormatter — probabilmente è un tutorial antico. Non usare BinaryFormatter: è stato rimosso da .NET 9 per motivi di sicurezza. La serializzazione binaria moderna è fornita da soluzioni esterne — per esempio, Protobuf o MessagePack.
2. Esempi semplici
Proviamo a mettere in pratica serializzazione e deserializzazione usando il nostro già noto classe Player dall'universo di gioco.
Prepariamo la classe per la serializzazione
// Player.cs
public class Player
{
public string Name { get; set; }
public int Health { get; set; }
public bool IsAlive { get; set; }
public List<string> Inventory { get; set; }
public Position Position { get; set; }
}
public class Position
{
public int X { get; set; }
public int Y { get; set; }
}
a) Serializzazione e deserializzazione in JSON con System.Text.Json
using System.Text.Json;
Player aragorn = new Player
{
Name = "Aragorn",
Health = 100,
IsAlive = true,
Inventory = new List<string> { "sword", "bow", "healing potion" },
Position = new Position { X = 10, Y = 25 }
};
// Serializzazione dell'oggetto Player in stringa JSON
string json = JsonSerializer.Serialize(aragorn);
// Stampiamo il JSON a schermo
Console.WriteLine(json);
// Deserializzazione della stringa JSON indietro nell'oggetto Player
Player? aragornClone = JsonSerializer.Deserialize<Player>(json);
// Controlliamo che il clone funzioni :)
Console.WriteLine(aragornClone?.Name); // Dovrebbe stampare "Aragorn"
È tutto molto semplice — nessun “ballo con il tamburello” o attributi magici. Ora vediamo come si presenta in XML.
b) Serializzazione e deserializzazione in XML con XmlSerializer
using System.Xml.Serialization;
// Configuriamo il serializer per la classe Player
XmlSerializer serializer = new XmlSerializer(typeof(Player));
// Serializzazione su file
using FileStream fs = new FileStream("aragorn.xml", FileMode.Create);
serializer.Serialize(fs, aragorn); // Salviamo Aragorn in un file XML
// Deserializzazione da file
using FileStream fs = new FileStream("aragorn.xml", FileMode.Open);
Player aragornFromXml = (Player) serializer.Deserialize(fs)!;
Console.WriteLine(aragornFromXml.Name); // Dovrebbe stampare "Aragorn"
Attenzione! XmlSerializer richiede che le classi e le loro proprietà siano pubbliche e abbiano un costruttore predefinito senza parametri (se ridefinisci il costruttore — rendilo public e senza parametri). Altrimenti la serializzazione fallirà con errore.
c) Serializzazione e deserializzazione in JSON con Newtonsoft.Json
using Newtonsoft.Json; // Non dimenticare di aggiungere il pacchetto Newtonsoft.Json via NuGet!
// Serializzazione
string json2 = JsonConvert.SerializeObject(aragorn);
// Deserializzazione
Player? aragornFromNewtonsoft = JsonConvert.DeserializeObject<Player>(json2);
Console.WriteLine(aragornFromNewtonsoft?.Name); // Ancora "Aragorn"
Appare quasi identico, ma Newtonsoft.Json ha molte più opzioni — per esempio, puoi serializzare campi privati, configurare il formatting e risolvere scenari non banali.
4. Dettagli utili
I serializer standard e le loro capacità
| Classe | Formato | Inclusa in .NET | Richiede pacchetto NuGet? | Adatta per file | Adatta per API | Semplicità |
|---|---|---|---|---|---|---|
|
JSON | Sì | No | Sì | Sì | Leggero |
|
JSON | No | Sì | Sì | Sì | Leggero |
|
XML | Sì | No | Sì | Spesso | Leggero |
Come scegliere quale classe usare?
Se non sai perché avresti bisogno di XML — quasi sempre scegli JSON e System.Text.Json. È più veloce, più semplice e conforme alle pratiche moderne.
XML conviene se:
- Ti integri con sistemi legacy che richiedono esattamente XML.
- Serve uno schema rigoroso e validazione della struttura dei dati.
- Le strutture sono grandi, stabili e serve compatibilità formale (impostazioni, config, integrazione con sistemi enterprise).
JSON — se:
- Stai costruendo un'app moderna, interagisci con il web e dispositivi mobili.
- Ti serve semplicità, leggibilità e compattezza.
- Non vuoi tirare dentro dipendenze extra.
Newtonsoft.Json — se:
- Ti serve serializzare campi privati, personalizzazioni particolari, completa flessibilità.
- O il progetto ha già questa libreria ereditata e migrare ora non è pratico.
5. Errori tipici e insidie
Encoding. I principali serializer (soprattutto quando si lavora con file) usano UTF-8 di default. Se vedi caratteri strani, controlla come leggi/scrivi i file e imposta esplicitamente l'encoding. Documentazione sulla configurazione dell'encoding.
Tipi non supportati. Alcuni serializer standard (soprattutto XML) non sanno serializzare per esempio i dizionari (Dictionary), campi privati/protected, eventi, delegate e interfacce. Di solito sono supportate proprietà pubbliche semplici e classi.
Versioni delle classi. Se cambi la struttura delle classi (aggiunto/rinominato/rimosso proprietà), i dati salvati in precedenza potrebbero non essere letti o deserializzati correttamente. Pianifica il versioning dei formati.
Valori null. Durante la deserializzazione, se nei dati manca un campo, la proprietà corrispondente riceverà il valore di default (per i tipi riferimento — null). Non dimenticare i controlli.
Attributi. Per configurazioni fini si usano spesso attributi come [JsonIgnore], [XmlElement] ecc. Permettono di escludere proprietà, cambiare nomi degli elementi e gestire il formato — approfondiremo nelle prossime lezioni.
GO TO FULL VERSION