1. Einführung
Newtonsoft.Json ist sozusagen ein Dinosaurier im besten Sinne. Es war über viele Jahre der De-facto-Standard für die Arbeit mit JSON im .NET-Ökosystem, noch bevor System.Text.Json überhaupt aufgetaucht ist. Millionen von Projekten, tausende Bibliotheken und Frameworks (sogar viele Teile von ASP.NET Core bis vor kurzem) haben genau Json.NET genutzt.
Seine Vorteile sind:
- Funktional reich und flexibel: Json.NET bietet eine riesige Menge an Einstellungen, Attributen und Möglichkeiten zur Anpassung des Serialisierungs-/Deserialisierungsprozesses. Es kann Dinge, die System.Text.Json nur mit viel Aufwand oder gar nicht kann.
- Tolerant gegenüber "unvollkommenem" JSON: Daten aus externen Systemen sind nicht immer ideal — Json.NET ist oft nachsichtiger und erlaubt Deserialisierung ohne unnötigen Ärger.
- Abwärtskompatibel: Wenn ein Projekt oder eine Bibliothek auf Json.NET aufbaut, bleibt es wichtig, damit umgehen zu können.
Klar, System.Text.Json ist schneller und für moderne Anforderungen entwickelt. Aber Newtonsoft.Json bleibt ein mächtiges Werkzeug, besonders wenn spezifische Logik oder maximale Flexibilität gebraucht wird.
Wie installiert man Newtonsoft.Json?
Weil es sich um eine Drittanbieter-Bibliothek handelt, füge das Paket über NuGet hinzu:
- Öffne das Projekt.
- Rechtsklick auf das Projekt im Solution Explorer.
- Wähle "Manage NuGet Packages...".
- Gib im Suchfeld Newtonsoft.Json ein.
- Wähle das Paket und klicke auf "Install".
Nach der Installation hast du eine neue Abhängigkeit — du kannst Json.NET verwenden!
Vergleich der Möglichkeiten von Newtonsoft.Json und System.Text.Json
| Funktion | System.Text.Json | Newtonsoft.Json |
|---|---|---|
| Einfache Serialisierung/Deserialisierung | Ja | Ja |
| Unterstützung von Attributen für Eigenschaften | Teilweise | Vollständig |
| Custom Converters | Ja | Ja |
| Arbeiten mit privaten Feldern | Nein | Ja |
| Arbeiten mit dynamischen Strukturen | Eingeschränkt | Ja |
| LINQ to JSON (JObject/JArray) | Nein | Ja |
| Reference Loop Handling | Ja | Ja |
| Unterstützung für DataTable, DataSet und komplexe Typen | Nein | Ja |
| Performance | Besser | Gut |
2. Beispiel: Serialisierung und Deserialisierung eines einfachen Objekts
Nehmen wir eine allgemeine Spielstruktur, die sich von Vorlesung zu Vorlesung entwickelt:
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; }
}
Jetzt speichern wir das Player-Objekt als JSON und stellen es wieder her:
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 }
};
// Serialisierung in einen JSON-String
string json = JsonConvert.SerializeObject(player1, Formatting.Indented);
Console.WriteLine(json);
// Deserialisierung zurück zu einem Player-Objekt
Player player2 = JsonConvert.DeserializeObject<Player>(json);
Console.WriteLine($"Name: {player2.Name}, Gesundheit: {player2.Health}");
Alles? Ja, fast, aber das ist nur die Spitze des Eisbergs. Schauen wir uns an, wodurch Newtonsoft.Json interessanter und flexibler als andere Bibliotheken ist.
3. Formatierung, Einstellungen und erweiterte Optionen
Wenn du ein Objekt serialisierst, kannst du eine kompakte String-Variante oder schön formatiertes JSON erhalten. Das Verhalten wird durch Parameter und Einstellungen gesteuert.
Beispiel: Verschiedene Formatierungsoptionen
// Schön lesbares JSON
string prettyJson = JsonConvert.SerializeObject(player1, Formatting.Indented);
// Kompaktes "minified" JSON
string compactJson = JsonConvert.SerializeObject(player1, Formatting.None);
Serializer-Einstellungen
Wenn nötig, übergib JsonSerializerSettings für feine Konfiguration:
var settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore, // Felder mit null weglassen
DefaultValueHandling = DefaultValueHandling.Ignore, // Felder mit Default-Werten weglassen
Formatting = Formatting.Indented
};
string customJson = JsonConvert.SerializeObject(player1, settings);
Du bekommst maximale Kontrolle über das Ausgabeformat: willst du leere Felder überspringen — kein Problem. Musst du sogar private Properties serialisieren — konfiguriere den Contract.
4. Steuerung von Feldern und Properties mit Attributen
Newtonsoft.Json unterstützt ein mächtiges Attributsystem, mit dem du die Serialisierung direkt in der Klasse anpassen kannst.
JsonProperty — Umbenennen von Properties
Wenn das JSON-Protokoll einen anderen Feldnamen verlangt:
public class Player
{
[JsonProperty("player_name")]
public string Name { get; set; }
// ...
}
Resultierendes JSON:
{ "player_name": "Aragorn", ... }
JsonIgnore — Property ignorieren
public class Player
{
[JsonIgnore]
public int Health { get; set; }
}
Jetzt verschwindet das Feld Health bei der Serialisierung.
JsonConverter — Benutzerdefinierte Konvertierungen
Erlaubt anzugeben, welcher Converter für ein konkretes Feld verwendet wird.
public class Player
{
[JsonConverter(typeof(InventoryToStringConverter))]
public List<string> Inventory { get; set; }
}
(Mehr zu Convertern weiter unten.)
5. Arbeiten mit verschachtelten Objekten und Collections
Json.NET kommt hervorragend mit verschachtelten Objekten, Arrays, Collections und Dictionaries klar.
Beispiel: Dictionaries
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);
Das JSON sieht dann so aus:
{
"Scores": {
"Alice": 1023,
"Bob": 999
}
}
6. Komplexe Strukturen: zyklische Referenzen, Self-Referencing Objects
Manchmal verweisen Objekte aufeinander. Newtonsoft.Json unterstützt die Serialisierung solcher Strukturen über spezielle Einstellungen.
Beispiel: Auflösen von zyklischen Referenzen
public class Person
{
public string Name { get; set; }
public Person Parent { get; set; }
public List<Person> Children { get; set; }
}
// Wir konfigurieren die Serialisierung für Zyklen
var settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore // oder .Serialize
};
Person p1 = new Person { Name = "Papa" };
Person p2 = new Person { Name = "Sohn", Parent = p1 };
p1.Children = new List<Person> { p2 };
string json = JsonConvert.SerializeObject(p1, settings);
Console.WriteLine(json);
Standardmäßig, wenn du ReferenceLoopHandling = Error lässt, bekommst du eine Ausnahme. Das schützt vor unbeabsichtigter unendlicher Serialisierung.
7. Arbeiten mit dynamischen Strukturen: JObject, JArray
Wenn die JSON-Struktur vorher unbekannt ist oder sich zur Laufzeit ändert, nutze dynamische Objekte ohne strikte C#-Typisierung.
Wichtige Typen:
- JObject — Repräsentation eines JSON-Objekts.
- JArray — Repräsentation eines Arrays.
using Newtonsoft.Json.Linq;
// Umwandlung eines Strings in ein JObject
string json = @"{ 'name': 'Aragorn', 'health': 100 }";
JObject obj = JObject.Parse(json);
Console.WriteLine((string)obj["name"]); // Aragorn
Console.WriteLine((int)obj["health"]); // 100
// Dynamisches Hinzufügen von Properties
obj["class"] = "Ranger";
Console.WriteLine(obj.ToString());
Iteration über ein Array
string jsonArr = @"['apple', 'banana', 'cherry']";
JArray array = JArray.Parse(jsonArr);
foreach (JToken item in array)
{
Console.WriteLine(item);
}
8. Unterstützung für Versionierung und Pflichtfelder
Das JSON-Format kann sich ändern, Felder können fehlen. Nutze Attribute und Einstellungen:
- [JsonProperty(Required = Required.Always)] — verlangt, dass das Feld vorhanden ist (sonst Exception).
- [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] — setzt Default ein, wenn das Feld fehlt.
public class Player
{
[JsonProperty(Required = Required.Always)]
public string Name { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[DefaultValue(50)]
public int Health { get; set; }
}
9. Datums- und Zeitformatierung
Mit Daten muss man oft ein explizites Format angeben.
var dateSettings = new JsonSerializerSettings
{
DateFormatString = "yyyy-MM-dd"
};
string json = JsonConvert.SerializeObject(DateTime.Now, dateSettings);
Console.WriteLine(json); // "2024-06-15"
Und zurück bei der Deserialisierung:
string dateJson = "\"2024-06-15\""; // Achtung: das ist ein String in Anführungszeichen!
DateTime dt = JsonConvert.DeserializeObject<DateTime>(dateJson);
Console.WriteLine(dt);
GO TO FULL VERSION