1. Perché scegliere un formato? Breve promemoria
Qualsiasi oggetto .NET in memoria è un insieme di indirizzi, riferimenti, campi, strutture interne e altra "cucina della macchina". Ma non puoi salvarlo così com'è in un file: i file devono essere strutturati in un formato che sappiano leggere (e preferibilmente scrivere) non solo noi, ma anche altri programmi. Qui entra in gioco la scelta del formato di serializzazione.
Compiti principali del formato di serializzazione:
- Compattezza: spazio su disco o velocità di trasmissione in rete.
- Leggibilità (umana!): è possibile aprire il file in un editor di testo e capire cosa c'è dentro.
- Universalità: è adatto per integrazione con altri sistemi e linguaggi?
- Supporto di strutture complesse: nidificazioni, collezioni, riferimenti, tipi.
- Sicurezza e compatibilità.
2. Serializzazione binaria (Binary Serialization)
Serializzazione binaria rappresenta i dati come un "raw" flusso binario di byte. Immagina di non aver semplicemente messo le cose in una scatola, ma di averle cementate — veloce, compatto, ma poi non trovi più i tuoi calzini senza un martello pneumatico.
// Esempio solo per memoria storica:
using System.Runtime.Serialization.Formatters.Binary;
// ... creazione dell'oggetto
var user = new User { Name = "Ivan", Age = 42 };
// Serializzazione
using var fs = new FileStream("user.bin", FileMode.Create);
var formatter = new BinaryFormatter();
formatter.Serialize(fs, user);
Pro:
- Compattezza: occupa pochissimo spazio su disco, alta velocità.
- Supporto integrato per i tipi "nativi" .NET.
Contro:
- Il formato è completamente illeggibile — prova ad aprire il file con il Blocco Note e entrerai nella Matrix (cioè otterrai una serie di caratteri illeggibili).
- Assolutamente non universale: solo per .NET (e anche solo per la stessa versione!).
- Vulnerabile a problemi di compatibilità tra versioni.
Dove veniva usato?
All'interno di .NET, quando serviva "dumpare" velocemente oggetti tra processi sulla stessa macchina. Oggi è fortemente NON raccomandato, soprattutto se tieni alla sicurezza e al mantenimento a lungo termine dell'applicazione. Usare BinaryFormatter nei progetti moderni è una cattiva pratica.
3. Formato XML (Extensible Markup Language)
XML è un formato leggibile da umani e macchine, basato su tag, come l'HTML, ma senza le battute sul <body>.
<User>
<Name>Ivan</Name>
<Age>42</Age>
</User>
Esempio di serializzazione:
using System.Xml.Serialization;
var user = new User { Name = "Ivan", Age = 42 };
var serializer = new XmlSerializer(typeof(User));
using var fs = new FileStream("user.xml", FileMode.Create);
serializer.Serialize(fs, user);
Pro:
- Leggibilità: puoi aprirlo e vedere la struttura a occhio.
- Universalità: molti linguaggi e programmi sanno leggere XML.
- Flessibilità (supporto di schemi, validazione, namespace ecc.).
- Adatto a strutture complesse e oggetti nidificati.
Contro:
- "Rumoroso" e pesante: occupa molto spazio e traffico.
- Parsing più lento rispetto ai formati binari.
- Imprecisioni nella serializzazione di alcuni tipi (per esempio date e orari).
- Richiede configurazioni aggiuntive per supportare alcune collezioni o oggetti non standard.
Dove si usa?
Scambio dati tra sistemi aziendali, config, integrazione con sistemi dove serve una struttura rigida.
4. Formato JSON (JavaScript Object Notation)
JSON è un formato compatto, leggero e facilmente leggibile, nato nel mondo JavaScript e diventato praticamente lo standard per lo scambio dati grazie alla sua sintesi e semplicità.
{
"Name": "Ivan",
"Age": 42
}
Esempio di serializzazione:
using System.Text.Json;
var user = new User { Name = "Ivan", Age = 42 };
string json = JsonSerializer.Serialize(user);
File.WriteAllText("user.json", json);
Pro:
- Molto leggibile sia per umani che per macchine.
- Si integra facilmente con tecnologie web (API, JavaScript e non solo).
- Più compatto di XML.
- Serializzazione/deserializzazione veloce con le librerie moderne (System.Text.Json, Newtonsoft.Json).
Contro:
- Nessun supporto per i commenti (il tuo JSON non potrà farsi una battuta).
- Limitazioni nella struttura: non serializza, per esempio, riferimenti tra oggetti o tipi complessi (es. dizionari con chiavi non-stringa).
- Divergenze nel formato di date/ore tra implementazioni diverse.
Dove si usa?
Praticamente ovunque serva scambiare informazioni tra piattaforme diverse: web services, app mobili, REST API ecc.
5. CSV (Comma-Separated Values)
CSV è un formato testuale semplice che rappresenta i dati come una tabella (righe e colonne), dove i campi sono separati da virgole o altri separatori.
Name,Age
Ivan,42
Olga,27
Esempio di scrittura CSV manuale:
// Per semplicità, scriviamo con un normale StreamWriter
var lines = new List<string>
{
"Name,Age",
"Ivan,42",
"Olga,27"
};
File.WriteAllLines("users.csv", lines);
Pro:
- Supportato da tantissimi programmi (Excel, Google Docs, DB ecc.).
- Conciso e comodo per dati tabellari.
Contro:
- Non adatto per oggetti nidificati o complessi (solo strutture "piatte").
- Non conserva i tipi di dato (tutto è stringa).
- Problemi di escaping se i dati contengono virgole, virgolette o ritorni a capo.
Dove si usa?
Export/import tra DB, scambio di semplici record, esportazioni da applicazioni per analisi.
6. Protocolli e formati con tipizzazione rigorosa
Protocol Buffers (protobuf) e MessagePack sono formati binari di serializzazione con contratti (schemi), che rendono la serializzazione ancora più compatta e veloce. Richiedono la descrizione preventiva della schema dei dati.
Esempio in protobuf (semplificato):
Non fa parte dello standard .NET, serve il package Google.Protobuf.
message User {
string name = 1;
int32 age = 2;
}
Pro:
- Velocità e compattezza massime.
- Cross-platform (molti linguaggi supportano protobuf).
Contro:
- Più complesso da imparare e configurare.
- Richiede generazione di codice a partire dallo schema.
- Non sempre necessario, se il progetto non gestisce milioni di messaggi al secondo.
Dove si usa?
Sistemi ad alto carico, scambio dati tra microservizi, giochi, IoT.
7. Dettagli utili
Tabella-confronto dei formati
| Formato | Leggibilità | Compattezza | Universalità | Oggetti complessi | Standard in .NET 9 | Sicurezza |
|---|---|---|---|---|---|---|
| Binary (.NET) | No | Sì | No | Sì | No | No |
| XML | Sì | No | Sì | Sì | Sì | Sì |
| JSON | Sì | Sì | Sì | Parzialmente | Sì | Sì |
| CSV | Sì | Sì | Sì | No | No | Sì |
| Protobuf | No | Il migliore | Sì | Sì | No | Sì |
Come scegliere il formato di serializzazione per la tua applicazione?
Devi salvare una struttura dati complessa e ti interessa la leggibilità umana — usa XML o JSON.
Serve trasferire rapidamente grandi quantità di dati tra servizi che controlli — prendi in considerazione protobuf o MessagePack.
Estratti di report per analisi in Excel o DB — usa CSV.
Stai scrivendo config per servizi o CI/CD — YAML ti tornerà molto utile.
Compattezza, velocità e supporto dei riferimenti tra oggetti sono critici? Dovrai guardare ai formati binari, ma ricorda i limiti di sicurezza e compatibilità.
8. Trucchi e errori comuni
Se decidi di conservare i dati in formato binario per "segretezza", ricorda: un dump binario non equivale a sicurezza. Un malintenzionato può comunque "smontare" quel flusso. Usa la cifratura se necessario.
Problema comune: dimenticare la codifica quando lavori con formati testuali (XML/JSON/CSV) — usa UTF-8. Non tutti gli editor e i sistemi gradiscono il BOM.
XML, anche se può sembrare "vecchio", è ottimo per protocolli contrattuali dove serve una descrizione di validazione rigida (per es. XSD), mentre JSON è più adatto per scambi veloci e flessibili.
Nella serializzazione di collezioni di oggetti complessi non tutti i formati supportano correttamente strutture nidificate o ricorsive. JSON e XML vanno d'accordo con array e liste, CSV no.
GO TO FULL VERSION