Zurück
25/10/2025
In nahezu jedem Projekt, an dem ich arbeite, kommt früher oder später der Moment, an dem Daten als JSON ein- oder ausgehen. Sei es eine API-Antwort, eine Konfigurationsdatei oder der Austausch zwischen zwei Services. In C# ist Newtonsoft.Json mein Werkzeug der Wahl dafür. In diesem Beitrag zeige ich, wie sich Klassen zu JSON serialisieren und JSON wieder zurück in Klassen deserialisieren lässt, und worauf es dabei ankommt.
Bevor wir loslegen, muss das Paket dem Projekt hinzugefügt werden. Das geschieht am einfachsten über den NuGet-Paketmanager mit folgendem Befehl.
dotnet add package Newtonsoft.JsonDanach steht uns der Namespace Newtonsoft.Json zur Verfügung, über den die gesamte Funktionalität erreichbar ist.
using Newtonsoft.Json;Damit wir etwas zum Arbeiten haben, definieren wir eine einfache Klasse. Sie repräsentiert einen Benutzer mit ein paar typischen Eigenschaften.
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public bool EmailVerified { get; set; }
}An diesem Beispiel zeige ich nun beide Richtungen: einmal von der Klasse zum JSON und einmal zurück.
Das Umwandeln eines Objekts in einen JSON-String nennt sich Serialisieren. Dafür stellt Newtonsoft die statische Methode JsonConvert.SerializeObject bereit.
var user = new User
{
Id = 1,
Name = "Valentin",
Email = "me@pndl.net",
EmailVerified = true
};
string json = JsonConvert.SerializeObject(user);Die Variable json enthält nun folgenden String.
{"Id":1,"Name":"Valentin","Email":"me@pndl.net","EmailVerified":true}Bei unserem kleinen Beispiel ist das gerade noch gut lesbar. Sobald das Objekt aber viele Felder oder verschachtelte Strukturen hat, wird so eine Zeile schnell unübersichtlich. Möchten wir das JSON eingerückt und übersichtlich haben, übergeben wir zusätzlich Formatting.Indented.
string json = JsonConvert.SerializeObject(user, Formatting.Indented);Das Ergebnis sieht dann deutlich aufgeräumter aus.
{
"Id": 1,
"Name": "Valentin",
"Email": "me@pndl.net",
"EmailVerified": true
}Der umgekehrte Weg, also vom JSON zurück zu einem Objekt, nennt sich Deserialisieren. In der Praxis liegt das JSON selten als fest einprogrammierter String vor, sondern kommt zum Beispiel aus einer Datei. Wir lesen den Inhalt daher mit File.ReadAllText aus einer user.json ein und übergeben ihn an JsonConvert.DeserializeObject. Über den generischen Parameter geben wir an, in welchen Typ das JSON umgewandelt werden soll.
string json = File.ReadAllText("user.json");
User user = JsonConvert.DeserializeObject<User>(json);Newtonsoft ordnet die JSON-Felder dabei automatisch den passenden Eigenschaften der Klasse zu. Auf das Objekt können wir nun ganz normal zugreifen.
Console.WriteLine(user.Name); // ValentinEin wichtiger Hinweis: Felder im JSON, die in der Klasse keine Entsprechung haben, werden standardmäßig einfach ignoriert. Umgekehrt bleiben Eigenschaften der Klasse, die im JSON fehlen, auf ihrem Standardwert (zum Beispiel 0 bei einem int oder null bei einem string).
In der Praxis stimmen die Namen im JSON oft nicht mit den C#-Konventionen überein. JSON nutzt häufig snake_case oder camelCase, während wir in C# PascalCase bevorzugen. Hier kommen Attribute ins Spiel, mit denen wir das Verhalten pro Eigenschaft steuern.
public class User
{
[JsonProperty("user_id")]
public int Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonIgnore]
public string Email { get; set; }
}[JsonProperty("user_id")]: Verknüpft die Eigenschaft Id mit dem JSON-Feld user_id. Das gilt in beide Richtungen, also beim Serialisieren und beim Deserialisieren.[JsonIgnore]: Schließt die Eigenschaft komplett aus. Sie taucht im erzeugten JSON nicht auf und wird beim Deserialisieren nicht befüllt. Praktisch für sensible oder berechnete Werte.Newtonsoft kommt auch mit komplexeren Strukturen problemlos zurecht. Verschachtelte Objekte und Listen müssen wir lediglich als Eigenschaften abbilden, der Rest passiert automatisch.
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public List<string> Roles { get; set; }
}
public class Address
{
public string City { get; set; }
public string Country { get; set; }
}Beim Serialisieren entsteht daraus ein verschachteltes JSON, das die Struktur exakt widerspiegelt.
{
"Id": 1,
"Name": "Valentin",
"Address": {
"City": "München",
"Country": "Deutschland"
},
"Roles": ["Admin", "Editor"]
}Beim Deserialisieren baut Newtonsoft die gesamte Objektstruktur inklusive Address und der Roles-Liste wieder korrekt auf.
Für mehr Kontrolle können wir ein JsonSerializerSettings-Objekt übergeben. Damit lassen sich viele Details auf einen Schlag konfigurieren. Zwei Einstellungen nutze ich besonders häufig.
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
string json = JsonConvert.SerializeObject(user, settings);Formatting = Formatting.Indented: Erzeugt das JSON gleich eingerückt und lesbar. Da die Formatierung nun Teil der Einstellungen ist, müssen wir sie nicht mehr separat an SerializeObject übergeben.ContractResolver = new CamelCasePropertyNamesContractResolver(): Wandelt sämtliche Eigenschaftsnamen automatisch in camelCase um, ohne dass wir jede einzelne mit [JsonProperty] versehen müssen. Aus EmailVerified wird so emailVerified.Mit Newtonsoft.Json lässt sich die Umwandlung zwischen Klassen und JSON in C# mit minimalem Aufwand erledigen. Für den Großteil der Fälle reichen die beiden Methoden SerializeObject und DeserializeObject völlig aus. Sobald es individueller wird, helfen Attribute wie [JsonProperty] und [JsonIgnore] oder die JsonSerializerSettings dabei, das Verhalten genau an die eigenen Anforderungen anzupassen.
In meinem nächsten Beitrag zeige ich dann, wie sich passend zu unseren Klassen ein JSON-Schema generieren lässt. Damit können wir vor dem Deserialisieren prüfen, ob das eingehende JSON überhaupt die erwartete Struktur hat, und so sicherstellen, dass wirklich nur das Richtige deserialisiert wird.