CodeGym /Kursy /C# SELF /Zastosowanie Newtonsoft.Js...

Zastosowanie Newtonsoft.Json

C# SELF
Poziom 44 , Lekcja 4
Dostępny

1. Wprowadzenie

Newtonsoft.Json to taki "dinozaur" w dobrym znaczeniu. Był on de facto standardem do pracy z JSON w ekosystemie .NET przez wiele lat, jeszcze zanim pojawił się System.Text.Json. Miliony projektów, tysiące bibliotek i frameworków (nawet wiele części ASP.NET Core do niedawna) korzystały właśnie z Json.NET.

Jego zalety to:

  • Bogactwo funkcji i elastyczność: Json.NET oferuje ogrom możliwości konfiguracji, atrybutów i sposobów dostosowania procesu serializacji i deserializacji. Potrafi robić rzeczy, które System.Text.Json albo robi z trudnością, albo wcale nie potrafi.
  • Tolerancyjność wobec "nieidealnego" JSON: dane z zewnętrznych systemów nie zawsze są idealne — Json.NET częściej sobie z tym radzi i pozwala deserializować bez zbędnego bólu.
  • Wsteczna kompatybilność: jeśli projekt lub biblioteka są zależne od Json.NET, umiejętność pracy z nim wciąż jest przydatna.

Oczywiście, System.Text.Json jest szybszy i zaprojektowany z myślą o nowoczesnych wymaganiach. Ale Newtonsoft.Json wciąż pozostaje potężnym narzędziem, zwłaszcza gdy potrzebujesz specyficznej logiki lub maksymalnej elastyczności.

Jak zainstalować Newtonsoft.Json?

Ponieważ to biblioteka zewnętrzna, dodaj pakiet przez NuGet:

  1. Otwórz projekt.
  2. Kliknij prawym przyciskiem na projekt w Solution Explorer.
  3. Wybierz "Manage NuGet Packages...".
  4. W polu wyszukiwania wpisz Newtonsoft.Json.
  5. Wybierz pakiet i kliknij "Install".

Po instalacji pojawi się nowe zależność — możesz używać Json.NET!

Porównanie możliwości Newtonsoft.Json i System.Text.Json

Możliwość System.Text.Json Newtonsoft.Json
Prosta serializacja/deserializacja Tak Tak
Wsparcie atrybutów dla właściwości Częściowo Pełna
Kustomne konwertery Tak Tak
Praca z prywatnymi polami Nie Tak
Praca z dynamicznymi strukturami Ograniczona Tak
LINQ to JSON (JObject/JArray) Nie Tak
Reference Loop Handling Tak Tak
Wsparcie DataTable, DataSet i złożonych typów Nie Tak
Wydajność Lepsza Dobra

2. Przykład serializacji i deserializacji prostego obiektu

Weźmy ogólną strukturę gry, która przewija się przez kolejne wykłady:

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; }
}

Teraz zapiszemy obiekt Player do JSON i przywrócimy go:

using Newtonsoft.Json;

Player player1 = new Player
{
    Name = "Aragorn",
    Health = 100,
    IsAlive = true,
    Inventory = new List<string> { "sword", "bow", "healing potion" },
    Position = new Position { X = 10, Y = 25 }
};

// Serializacja do ciągu JSON
string json = JsonConvert.SerializeObject(player1, Formatting.Indented);
Console.WriteLine(json);

// Deserializacja z powrotem do obiektu Player
Player player2 = JsonConvert.DeserializeObject<Player>(json);
Console.WriteLine($"Imię: {player2.Name}, zdrowie: {player2.Health}");

To wszystko? Prawie, ale to tylko wierzchołek góry lodowej. Zobaczmy, co czyni Newtonsoft.Json ciekawszym i bardziej elastycznym od innych bibliotek.

3. Formatowanie, ustawienia i zaawansowane opcje

Kiedy serializujesz obiekt, możesz uzyskać zarówno kompaktowy ciąg, jak i ładnie sformatowany JSON. Zachowanie kontrolujesz parametrami i ustawieniami.

Przykład: Różne warianty formatowania

// Ładnie czytelny JSON
string prettyJson = JsonConvert.SerializeObject(player1, Formatting.Indented);

// Kompaktowy "minifikowany" JSON
string compactJson = JsonConvert.SerializeObject(player1, Formatting.None);

Ustawienia serializacji

W razie potrzeby przekaż JsonSerializerSettings dla precyzyjnej konfiguracji:

var settings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore, // Pomijaj pola o wartości null
    DefaultValueHandling = DefaultValueHandling.Ignore, // Pomijaj pola z wartością domyślną
    Formatting = Formatting.Indented
};
string customJson = JsonConvert.SerializeObject(player1, settings);

Masz pełną kontrolę nad formatem wyjścia: chcesz pominąć puste pola — proszę bardzo. Potrzebujesz serializować nawet prywatne właściwości — skonfiguruj kontrakt.

4. Zarządzanie polami i właściwościami za pomocą atrybutów

Newtonsoft.Json wspiera potężny system atrybutów, które konfigurują serializację bezpośrednio w klasie.

JsonProperty — Zmiana nazwy właściwości

Jeśli protokół JSON wymaga innej nazwy pola:

public class Player
{
    [JsonProperty("player_name")]
    public string Name { get; set; }
    // ...
}

Wynikowy JSON:

{ "player_name": "Aragorn", ... }

JsonIgnore — Ignorowanie właściwości

public class Player
{
    [JsonIgnore]
    public int Health { get; set; }
}

Teraz pole Health zniknie podczas serializacji.

JsonConverter — Własne konwersje

Pozwala wskazać, którym konwerterem ma być obsługiwane konkretne pole.

public class Player
{
    [JsonConverter(typeof(InventoryToStringConverter))]
    public List<string> Inventory { get; set; }
}

(Więcej o konwerterach — poniżej.)

5. Praca z obiektami zagnieżdżonymi i kolekcjami

Json.NET świetnie radzi sobie z obiektami zagnieżdżonymi, tablicami, kolekcjami i słownikami.

Przykład: Słowniki

public class GameStats
{
    public Dictionary<string, int> Scores { get; set; }
}

GameStats stats = new GameStats
{
    Scores = new Dictionary<string, int>
    {
        ["Alice"] = 1023,
        ["Bob"] = 999
    }
};

string statsJson = JsonConvert.SerializeObject(stats, Formatting.Indented);
Console.WriteLine(statsJson);

JSON będzie wyglądać tak:

{
  "Scores": {
    "Alice": 1023,
    "Bob": 999
  }
}

6. Złożone struktury: cykliczne referencje, Self-Referencing Objects

Czasem obiekty zawierają referencje do siebie nawzajem. Newtonsoft.Json wspiera serializację takich struktur przez specjalne ustawienia.

Przykład: Rozwiązywanie cyklicznych referencji

public class Person
{
    public string Name { get; set; }
    public Person Parent { get; set; }
    public List<Person> Children { get; set; }
}

// Konfigurujemy serializację dla cykli
var settings = new JsonSerializerSettings
{
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore // lub .Serialize
};

Person p1 = new Person { Name = "Tata" };
Person p2 = new Person { Name = "Syn", Parent = p1 };
p1.Children = new List<Person> { p2 };

string json = JsonConvert.SerializeObject(p1, settings);
Console.WriteLine(json);

Domyślnie, jeśli zostawisz ReferenceLoopHandling = Error, dostaniesz wyjątek. Chroni to przed przypadkową nieskończoną serializacją.

7. Praca ze strukturami dynamicznymi: JObject, JArray

Gdy struktura JSON nie jest znana z góry lub zmienia się w locie, użyj dynamicznych obiektów bez ścisłej typizacji po stronie C#.

Podstawowe typy:

  • JObject — reprezentacja obiektu JSON.
  • JArray — reprezentacja tablicy.
using Newtonsoft.Json.Linq;

// Konwersja stringa do JObject
string json = @"{ 'name': 'Aragorn', 'health': 100 }";
JObject obj = JObject.Parse(json);

Console.WriteLine((string)obj["name"]); // Aragorn
Console.WriteLine((int)obj["health"]);  // 100

// Dynamiczne dodawanie właściwości
obj["class"] = "Ranger";
Console.WriteLine(obj.ToString());

Iteracja po tablicy

string jsonArr = @"['apple', 'banana', 'cherry']";
JArray array = JArray.Parse(jsonArr);

foreach (JToken item in array)
{
    Console.WriteLine(item);
}

8. Wsparcie wersjonowania i pól obowiązkowych

Format JSON może się zmieniać, pola mogą nie występować. Użyj atrybutów i ustawień:

  • [JsonProperty(Required = Required.Always)] — wymaga obecności pola (w przeciwnym razie wyjątek).
  • [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] — podstawia wartość domyślną, jeśli pole nie występuje.
public class Player
{
    [JsonProperty(Required = Required.Always)]
    public string Name { get; set; }

    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
    [DefaultValue(50)]
    public int Health { get; set; }
}

9. Konwersja dat i formaty czasu

Praca z datami często wymaga jawnego formatu.

var dateSettings = new JsonSerializerSettings
{
    DateFormatString = "yyyy-MM-dd"
};
string json = JsonConvert.SerializeObject(DateTime.Now, dateSettings);
Console.WriteLine(json); // "2024-06-15"

A także przy deserializacji:

string dateJson = "\"2024-06-15\""; // Uwaga: to jest string w cudzysłowie!
DateTime dt = JsonConvert.DeserializeObject<DateTime>(dateJson);
Console.WriteLine(dt);
2
Zadanie
C# SELF, poziom 44, lekcja 4
Niedostępne
Użycie atrybutów JsonProperty i JsonIgnore
Użycie atrybutów JsonProperty i JsonIgnore
1
Ankieta/quiz
Standardowe klasy serializacji, poziom 44, lekcja 4
Niedostępny
Standardowe klasy serializacji
Klasy i biblioteki do serializacji
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION