1. Einführung
Alles gut, wenn deine Anforderungen dem Default-Verhalten entsprechen. Aber oft verlangt der Kunde (oder ein fremdes Backend) ein sehr spezifisches Format: überall camelCase, Datumsangaben im ISO 8601-Stil, null-Auslassungen, custom Converter und sonstige Freuden der Integration.
Hier kommt unser neuer Freund ins Spiel — die Klasse JsonSerializerOptions.
Wenn Serialisierung eine Küche wäre, ist diese Klasse deine Gewürzsammlung, Töpfe und geheimen Zutaten, mit denen du die Serialisierung nach deinem Geschmack würzen kannst.
Wie du JsonSerializerOptions benutzt
Um den Serialisierungs- oder Deserialisierungsprozess anzupassen, übergibst du einfach ein Options-Objekt an die Methoden des Serializers:
using System.Text.Json;
var options = new JsonSerializerOptions
{
// Hier kommen deine Einstellungen
};
string json = JsonSerializer.Serialize(myObject, options);
var obj = JsonSerializer.Deserialize<MyType>(json, options);
Dieses Muster sieht man überall: du erstellst ein JsonSerializerOptions, passt es an (siehe unten) und gibst es an die Serializer-Methoden Serialize/Deserialize weiter.
Wichtig: Dasselbe JsonSerializerOptions-Objekt kann (und sollte) für mehrere Serialisierungen wiederverwendet werden.
2. Grundlegende Einstellungen von JsonSerializerOptions
Schauen wir uns die beliebtesten "Regler" und "Schalter" dieser Klasse an.
JSON-Formatierung — WriteIndented
Stören dich einzeilige JSON-Ketten? Kein Problem — aktiviere hübsche Einrückungen!
var options = new JsonSerializerOptions
{
WriteIndented = true // Schönes, "menschliches" JSON
};
var person = new Person { Name = "Anna", Age = 30 };
string json = JsonSerializer.Serialize(person, options);
Console.WriteLine(json);
Ausgabe:
{
"Name": "Anna",
"Age": 30
}
Ohne WriteIndented = true hättest du das triste {"Name":"Anna","Age":30}. Im Production-Umfeld nutzt man meist minifizierten JSON (spart Platz), für Debugging und Logs nimmt man formatierten JSON.
Namenkonventionen — PropertyNamingPolicy
Oft verlangt ein API, dass Property-Namen im camelCase sind (z. B. firstName statt FirstName). In .NET sind Properties normalerweise PascalCase — hier hilft die Eigenschaft PropertyNamingPolicy:
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
var person = new Person { Name = "Oleg", Age = 25 };
string json = JsonSerializer.Serialize(person, options);
Console.WriteLine(json); // {"name":"Oleg","age":25}
Wenn du einen eigenen Stil brauchst (z. B. ALLE GROSSBUCHSTABEN), kannst du eine eigene Implementierung von JsonNamingPolicy schreiben. Meistens reicht CamelCase aber aus.
3. Eigenschaften ignorieren
null-Werte überspringen oder nicht — DefaultIgnoreCondition
Manchmal sollen Felder mit leeren (null) Werten gar nicht im JSON auftauchen. Gründe: kompakteres JSON oder ein externes System, das nicht gut mit null klarkommt.
Dafür nutzt du die Eigenschaft DefaultIgnoreCondition:
using System.Text.Json.Serialization;
var options = new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
var person = new Person { Name = null, Age = 22 };
string json = JsonSerializer.Serialize(person, options);
Console.WriteLine(json); // {"Age":22}
Wenn du nicht nur null, sondern auch Default-Werte ignorieren willst (z. B. int=0), verwende WhenWritingDefault:
options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault;
Felder einbeziehen — IncludeFields und [JsonInclude]
Standardmäßig werden nur öffentliche Properties mit offenem Setter serialisiert. Wenn du auch Felder (fields) serialisieren möchtest, kannst du das einschalten:
var options = new JsonSerializerOptions
{
IncludeFields = true
};
Beispielklasse:
public class Item
{
public string Name;
public int Id { get; set; }
}
var item = new Item { Name = "Book", Id = 12 };
string json = JsonSerializer.Serialize(item, options);
// {"Name":"Book","Id":12}
Für die Serialisierung privater Felder/Properties kannst du das Attribut [JsonInclude] verwenden, aber das ist Thema einer anderen Vorlesung.
4. Wertkonvertierung
Datumsformatierung — Converters
Standardmäßig serialisiert System.Text.Json Daten strikt im ISO 8601-Format (z. B. "2023-12-27T15:30:45.123Z"), was meist praktisch ist. Es gibt aber Fälle, in denen ein spezielles Datums-/Zeitformat gefordert ist.
Dafür hängst du eigene Converter an. Ein simples Beispiel:
using System.Text.Json;
using System.Text.Json.Serialization;
public class CustomDateTimeConverter : JsonConverter<DateTime>
{
private string _format = "yyyyMMdd";
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var date = reader.GetString();
return DateTime.ParseExact(date, _format, null);
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString(_format));
}
}
// Converter benutzen
var options = new JsonSerializerOptions();
options.Converters.Add(new CustomDateTimeConverter());
var dateObj = new { Date = new DateTime(2022, 1, 5) };
string json = JsonSerializer.Serialize(dateObj, options); // {"Date":"20220105"}
5. Nützliche Hinweise
Groß-/Kleinschreibung bei der Deserialisierung ignorieren — PropertyNameCaseInsensitive
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
var json = "{\"name\":\"Vasya\",\"age\":33}";
var person = JsonSerializer.Deserialize<Person>(json, options);
// person.Name == "Vasya"
Verschachtelung und maximale Objekt-Tiefe steuern — MaxDepth
var options = new JsonSerializerOptions
{
MaxDepth = 32 // Standard ist 64
};
Wenn deine Objekte extrem tief verschachtelt sein können — zum Beispiel ein Baum mit Verweisen auf Eltern und Kinder — dann ist es besser, das Modell anders zu gestalten.
Kommentare in JSON — ReadCommentHandling (Deserialisierung)
JSON unterstützt offiziell keine Kommentare, aber manchmal trifft man auf "kreative" Dateien mit //-Kommentaren.
var options = new JsonSerializerOptions
{
ReadCommentHandling = JsonCommentHandling.Skip
};
string json = "{\n \"Name\": \"Ivan\", // Benutzername\n \"Age\": 30\n}";
var person = JsonSerializer.Deserialize<Person>(json, options);
Sonderzeichen-Unterstützung — Encoder
Manchmal möchtest du kontrollieren, wie der Serializer Zeichen escaped (z. B. damit Kyrillisch nicht in \uXXXX umgewandelt wird). Du kannst einen eigenen Encoder angeben:
using System.Text.Encodings.Web;
var options = new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
Vorsicht: Nutze das mit Bedacht, sonst könnten Emojis oder Schriftzeichen plötzlich in Unicode-Sequenzen "verschwinden"!
6. Typische Fehler bei der Konfiguration der Serialisierung
Fehler Nr.1: Den öffentlichen Setter vergessen. Feld oder Property wird nicht serialisiert, weil kein öffentlicher Setter vorhanden ist oder es privat ist.
Fehler Nr.2: Falsches Ignorieren von null-Werten. Bei aktivierter DefaultIgnoreCondition landen Properties mit null nicht im JSON, obwohl du das vielleicht nicht erwartet hast.
Fehler Nr.3: Falsches Datumsformat. Das Datum wird nicht im gewünschten Format serialisiert — hänge einen custom Converter (JsonConverter) an.
Fehler Nr.4: Erwartung einer festen Reihenfolge der Properties. Der JSON-Standard garantiert keine Feldreihenfolge. Wenn ein API eine strikte Reihenfolge verlangt, musst du entweder das Modell ändern oder auf Drittanbieter-Bibliotheken ausweichen.
Fehler Nr.5: Unterschiedliche Einstellungen beim Serialisieren und Deserialisieren. Wenn du nicht dieselben JsonSerializerOptions für Schreiben und Lesen verwendest, kann es zu Problemen kommen — z. B. mit Namens-Casing oder Formaten.
GO TO FULL VERSION