CodeGym /Kursy /C# SELF /Przegląd standardowych klas serializacji w .NET

Przegląd standardowych klas serializacji w .NET

C# SELF
Poziom 44 , Lekcja 0
Dostępny

1. Wprowadzenie

Skoro postanowiliśmy „rozebrać LEGO-figurkę na części”, to rozróbmy, jakie mamy do tego narzędzia w .NET. Innymi słowy — jakie standardowe klasy pomagają serializować i deserializować obiekty do różnych formatów i co stoi za każdym z nich.

Jak zorganizowana jest rodzina serializacyjna .NET

Na bieżący (2025) moment .NET oferuje kilka podstawowych podejść do serializacji, każde z własnym zestawem klas i narzędzi. Główne i najczęściej spotykane:

  • Serializacja JSON — podstawowa i najbardziej nowoczesna opcja, używana w większości projektów.
  • Serializacja XML — trochę bardziej staroświecka, ale wciąż aktywnie stosowana.
  • Serializacja binarna — tylko na specjalne przypadki i zwykle przez nowoczesne rozwiązania zewnętrzne.

Wiele przykładów i większość kodu w .NET 9 używa właśnie JSON, i to nie moda — to przemysłowy standard. Ale .NET wspiera też inne sposoby — na wszelki wypadek.

Główni bohaterowie serializacji .NET

Format Klasa serializacji Prostota Wydajność Bezpieczeństwo Aktualność
JSON
System.Text.Json
🔥🔥🔥 🔥🔥🔥 🔥🔥🔥 Najbardziej aktualny
XML
System.Xml.Serialization.XmlSerializer
🔥🔥 🔥🔥 🔥🔥 Używany
JSON Newtonsoft.Json (Json.NET) 🔥🔥🔥 🔥🔥 🔥🔥🔥 Bardzo popularny

Krótko o każdym

  • System.Text.Json: Nowy standard serializacji JSON w .NET, pojawił się w .NET Core 3.0, stał się domyślnym w .NET 5+. Szybki, lekki, bezpieczny, wbudowany „out of the box” w .NET 9. Dokumentacja
  • XmlSerializer: Stara i sprawdzona opcja do serializacji do XML. Prosty w użyciu, ale z ograniczeniami (np. wymaga public-klasy i publicznych właściwości). Dobry do kompatybilności i ścisłych kontraktów danych. Dokumentacja
  • Newtonsoft.Json: Przez długi czas był de-facto standardem serializacji JSON przed pojawieniem się System.Text.Json. Często używany w skomplikowanych scenariuszach (dynamika, prywatne właściwości itp.). Dokumentacja

Gdzie podział się BinaryFormatter?

Jeśli trafisz w sieci na porady używania BinaryFormatter — najpewniej to stary tutorial. Nie używaj BinaryFormatter: został usunięty z .NET 9 ze względów bezpieczeństwa. Współczesną serializację binarną zapewniają zewnętrzne rozwiązania — np. Protobuf lub MessagePack.

2. Proste przykłady

Spróbujmy zastosować w praktyce serializację i deserializację na przykładzie naszego znanego już klasy Player z uniwersum gry.

Przygotujmy klasę do serializacji

// 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) Serializacja i deserializacja do JSON przy pomocy 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 }
};

// Serializacja obiektu Player do stringa JSON
string json = JsonSerializer.Serialize(aragorn);
// Wypiszmy JSON na ekran
Console.WriteLine(json);

// Deserializacja stringa JSON z powrotem do obiektu Player
Player? aragornClone = JsonSerializer.Deserialize<Player>(json);
// Sprawdźmy, czy klon działa :)
Console.WriteLine(aragornClone?.Name); // Powinno wypisać "Aragorn"

Tak to proste — żadnych „tańców z bębenkiem” i magicznych atrybutów. A teraz — jak to wygląda w XML.

b) Serializacja i deserializacja do XML przy pomocy XmlSerializer

using System.Xml.Serialization;

// Skonfigurujemy serializer dla klasy Player
XmlSerializer serializer = new XmlSerializer(typeof(Player));

// Serializacja do pliku
using FileStream fs = new FileStream("aragorn.xml", FileMode.Create);
serializer.Serialize(fs, aragorn); // Zapisujemy Aragorn do pliku XML

// Deserializacja z pliku
using FileStream fs = new FileStream("aragorn.xml", FileMode.Open);
Player aragornFromXml = (Player) serializer.Deserialize(fs)!;
Console.WriteLine(aragornFromXml.Name); // Powinno wypisać "Aragorn"

Uwaga! XmlSerializer wymaga, żeby klasy i ich właściwości były publiczne i miały domyślny konstruktor bez parametrów (jeśli nadpisujesz konstruktor — zrób go public i bez parametrów). W przeciwnym razie serializacja zakończy się błędem.

c) Serializacja i deserializacja do JSON przy pomocy Newtonsoft.Json

using Newtonsoft.Json; // Nie zapomnij dodać pakietu Newtonsoft.Json przez NuGet!

// Serializacja
string json2 = JsonConvert.SerializeObject(aragorn);

// Deserializacja
Player? aragornFromNewtonsoft = JsonConvert.DeserializeObject<Player>(json2);

Console.WriteLine(aragornFromNewtonsoft?.Name); // Znowu "Aragorn"

Wygląda prawie tak samo, ale Newtonsoft.Json ma wiele dodatkowych opcji — np. można serializować prywatne pola, konfigurować formatowanie i rozwiązywać nietrywialne scenariusze.

4. Przydatne niuanse

Standardowe serializatory i ich możliwości

Klasa Format Wbudowana w .NET Wymaga pakietu NuGet? Przydatna do plików Przydatna do API Prostota
System.Text.Json
JSON Tak Nie Tak Tak Lekki
Newtonsoft.Json
JSON Nie Tak Tak Tak Lekki
XmlSerializer
XML Tak Nie Tak Często Lekki

Jak dowiedzieć się, której klasy użyć?

Jeśli nie wiesz, po co ci XML — prawie zawsze wybieraj JSON i System.Text.Json. To szybsze, prostsze i zgodne z nowoczesnymi praktykami.

XML warto wybierać, jeśli:

  • Integrujesz się ze starymi systemami, które wymagają właśnie XML.
  • Potrzebna jest ścisła schema i walidacja struktury danych.
  • Struktury są duże, stabilne i ważna jest formalna kompatybilność (ustawienia, configi, wymiana z systemami enterprise).

JSON — jeśli:

  • Tworzysz nowoczesną aplikację, komunikujesz się z webem i urządzeniami mobilnymi.
  • Potrzebujesz prostoty, czytelności i kompaktowości.
  • Nie chcesz ciągnąć dodatkowych zależności.

Newtonsoft.Json — jeśli:

  • Potrzebujesz serializacji prywatnych pól, specjalnych customizacji, pełnej elastyczności.
  • Albo projekt już dziedziczy tę bibliotekę i migracja teraz nie ma sensu.

5. Typowe błędy i pułapki

Kodowanie. Główne klasy serializacji (szczególnie przy pracy z plikami) używają domyślnie UTF-8. Jeśli widzisz „krzaczki”, sprawdź, jak czytasz/zapisujesz pliki i czy ustawiłeś jawnie kodowanie. Dokumentacja o konfiguracji kodowania.

Typy nieobsługiwane. Niektóre standardowe serializatory (zwłaszcza XML) nie potrafią serializować np. słowników (Dictionary), prywatnych/protected-pól, eventów, delegatów i interfejsów. Zwykle wspierane są publiczne proste właściwości i klasy.

Wersje klas. Jeśli zmieniasz strukturę klas (dodałeś/przemianowałeś/usunąłeś właściwości), stare zapisane dane mogą nie dać się odczytać albo zdeserializować niepoprawnie. Planuj wersjonowanie formatów.

Null-wartości. Przy deserializacji, jeśli w danych brakuje jakiegoś pola, odpowiadające mu właściwość dostanie wartość domyślną (dla typu referencyjnego — null). Nie zapomnij o walidacjach.

Atrybuty. Do precyzyjnej konfiguracji często używa się atrybutów typu [JsonIgnore], [XmlElement] itd. Pozwalają wykluczać właściwości, zmieniać nazwy elementów i kontrolować format — szczegóły w kolejnych wykładach.

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