CodeGym /Corsi /C# SELF /Esempi base di serializzazione

Esempi base di serializzazione

C# SELF
Livello 45 , Lezione 0
Disponibile

1. Introduzione

Promemoria: La serializzazione è un modo per salvare lo stato di un oggetto come stringa, file o stream, così poi si può ricostruire quell'oggetto (deserializzare) — e si ottiene di nuovo l'oggetto con gli stessi dati.

Situazione tipica:
1) Hai un oggetto, per esempio un utente con nome ed età.
2) Devi salvarlo — inviarlo in rete, scriverlo su file o, diciamo, nel formato JSON.
3) Poi prendi i dati dalla stringa/file e li ricostruisci — e ottieni di nuovo l'oggetto!

In C# si fa in poche righe. Vediamo come.

La nostra applicazione

Stiamo sviluppando una piccola app "Contact Manager". Supponiamo di avere la classe Person che vogliamo serializzare.

public class Person
{
    // Le proprietà pubbliche sono necessarie per la serializzazione!
    public string Name { get; set; }
    public int Age { get; set; }

    // Il costruttore senza parametri è obbligatorio per XmlSerializer
    public Person() { }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

Se non conosci questa sintassi, non preoccuparti — più avanti nel corso analizzeremo classi e proprietà in dettaglio. Per ora consideralo come modello dati per gli esperimenti. Nota: le proprietà pubbliche Name e Age sono importanti per la serializzazione, e per XmlSerializer serve un costruttore pubblico senza parametri.

2. Serializzazione in JSON con System.Text.Json

Esempio minimale

Promesso — eccolo! Così si serializza in JSON:

using System;
using System.Text.Json;

Person person = new Person("Alisa", 28);

// Serializzazione: trasformiamo l'oggetto in una stringa JSON
string json = JsonSerializer.Serialize(person);

Console.WriteLine("JSON:");
Console.WriteLine(json);

Cosa vedrai in output?

JSON:
{"Name":"Alisa","Age":28}

Tutto semplice: oggetto → JSON. Ecco la magia!

Deserializzazione — riportiamo tutto indietro

Ora facciamo l'operazione inversa — dalla stringa JSON ricostruiamo l'oggetto:

string json = "{\"Name\":\"Bob\",\"Age\":35}";

// Deserializzazione: ricostruiamo un oggetto di tipo Person dalla stringa JSON
Person restored = JsonSerializer.Deserialize<Person>(json);

Console.WriteLine("Oggetto ricostruito:");
Console.WriteLine($"Nome: {restored.Name}, età: {restored.Age}");

Risultato:

Oggetto ricostruito:
Nome: Bob, età: 35

Nota: se la struttura dei dati non combacia (per esempio manca una proprietà), il campo corrispondente rimarrà con il valore di default (null per i tipi reference, 0 per i numeri, ecc.).

3. Serializzazione/deserializzazione in XML con XmlSerializer

Serializzare in XML — prima occhiata

using System;
using System.IO;
using System.Xml.Serialization;

Person person = new Person("Katja", 22);

// Creiamo il serializer per il tipo Person
var serializer = new XmlSerializer(typeof(Person));

// Scriviamo l'XML in un file
using (var stream = new FileStream("person.xml", FileMode.Create))
{
    serializer.Serialize(stream, person);
    // Lo stream si chiuderà automaticamente al termine del using
}
Console.WriteLine("File XML creato!");

Nel file person.xml apparirà qualcosa del genere:

<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>Katja</Name>
  <Age>22</Age>
</Person>

Punto importante:
Per serializzare in file si usa uno stream (Stream, ad es. FileStream). Se vuoi serializzare in una stringa (per invio in rete), usa StringWriter:

var serializer = new XmlSerializer(typeof(Person));
using (var sw = new StringWriter())
{
    serializer.Serialize(sw, person);
    string xmlString = sw.ToString();
    Console.WriteLine(xmlString);
}

Deserializzare da XML

using (var stream = new FileStream("person.xml", FileMode.Open))
{
    // Non dimenticare il casting al tipo corretto!
    Person restored = (Person)serializer.Deserialize(stream);
    Console.WriteLine($"Nome: {restored.Name}, età: {restored.Age}");
}

Ancora: XmlSerializer richiede che la classe serializzabile abbia un costruttore pubblico di default (senza parametri).

4. Lavorare con file e stringhe: cosa scegliere?

Nella vita reale la serializzazione può essere direttamente in una stringa (per invio in rete/salvataggio in DB) oppure in un file (per storage a lungo termine).

Serializzazione in stringa (per esempio per invio via API):

  • JSON: usa JsonSerializer.Serialize(obj).
  • XML: tramite StringWriter.

Serializzazione in file (per esempio per export/backup):

  • JSON: salva la stringa su file con gli strumenti standard di file I/O.
  • XML: scrivi direttamente nello stream con XmlSerializer.

Esempio: serializzare su file e leggere (JSON)

using System.IO;
using System.Text.Json;

Person person = new Person("Tom", 42);

// Serializzazione in stringa
string json = JsonSerializer.Serialize(person);

// Scrittura su file
File.WriteAllText("contact.json", json);

// Lettura dal file
string readJson = File.ReadAllText("contact.json");
Person restored = JsonSerializer.Deserialize<Person>(readJson);

Console.WriteLine($"{restored.Name}, età: {restored.Age}");

5. Confronto JSON vs XML

Visualizzazione del processo

Per non confondersi, ecco lo schema del processo di serializzazione e deserializzazione:

flowchart LR
    A[Oggetto] -- serializzazione --> B[Stringa/File/Stream]
    B -- deserializzazione --> C[Oggetto]

    A -. JSON o XML .-> B
    B -. JSON o XML .-> C

Puoi pensare alla serializzazione come "fare la valigia", e alla deserializzazione come "disfare la valigia" a casa.

Tabella di confronto

Funzionalità JSON (System.Text.Json) XML (XmlSerializer)
Lettura/scrittura in stringa ++ +
Lettura/scrittura in file ++ ++
Richiede costruttore senza parametri No
Readability per umani ++ +
Schema di dati rigido (validazione) - ++
Flessibilità (attributi di customizzazione) + ++
Performance ++ +
Compatibilità con internet ++ +

++ — molto bene, + — normale, - — non supportato

6. Come aggiungere la serializzazione alla nostra app

Immaginiamo che in "Contact Manager" sia stata aggiunta la funzione per salvare la lista di contatti su file e ripristinarla.

Contesto: abbiamo una lista di contatti (List<Person>).

List<Person> contacts = new List<Person>
{
    new Person("Vasya", 30),
    new Person("Petya", 25),
    new Person("Masha", 27)
};

// Salviamo tutti i contatti — serializziamo in JSON
string jsonContacts = JsonSerializer.Serialize(contacts);
File.WriteAllText("contacts.json", jsonContacts);

// Ripristiniamo la lista di contatti
string readContactsJson = File.ReadAllText("contacts.json");
List<Person> restored = JsonSerializer.Deserialize<List<Person>>(readContactsJson);

foreach (var c in restored)
{
    Console.WriteLine($"{c.Name}, età: {c.Age}");
}

La stessa cosa si può fare con XML, ma ci sono delle particolarità. Per serializzare collezioni con XmlSerializer spesso si avvolge la lista in una classe contenitore (elemento radice) — così è più semplice controllare il formato e i nomi degli elementi.

7. Errori tipici durante serializzazione e deserializzazione

Errore №1: mismatch dei tipi durante serializzazione/deserializzazione.
Hai serializzato List<Person> — devi deserializzare nello stesso tipo List<Person>, non in List<object> o IEnumerable<Person>. Altrimenti otterrai un'eccezione o risultati inattesi.

Errore №2: tentare di serializzare campi/proprietà non pubblici.
I serializer tipici (JsonSerializer, XmlSerializer) lavorano con membri pubblici. Se una proprietà non ha getter/setter pubblico, il valore potrebbe non finire nel JSON/XML, e ti chiederai perché è null.

Errore №3: mancanza del costruttore senza parametri.
Per XmlSerializer il costruttore pubblico di default è obbligatorio. Se non c'è — si verifica un'eccezione in fase di deserializzazione.

Errore №4: fraintendere i riferimenti agli oggetti.
Se un oggetto contiene riferimento a un altro, la serializzazione avviene "per valore" (come oggetto annidato). I riferimenti in sé non sono preservati, il che può causare duplicazione dei dati o problemi con riferimenti ciclici.

Errore №5: cercare di mescolare formati di serializzazione.
XML e JSON sono formati diversi con serializer diversi. Non puoi passare una stringa JSON a XmlSerializer e viceversa — otterrai un errore.

Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION