Neu in .NET 8.0 [29]: Verbesserungen fĂĽr den JSON-Source-Generator
Der Source Generator ist in .NET 8.0 wichtiger, damit die JSON-Serialisierung und -Deserialisierung auch AOT-Anwendungen funktioniert.​

(Bild: RossEdwardCairney/Shutterstock.com)
- Dr. Holger Schwichtenberg
System.Text.Json
nimmt im Standard das Mapping von JSON auf .NET-Objekte per Laufzeitcodegenerierung vor. Schon seit der Version 6.0 gibt es in System.Text.Json
auch einen Source-Generator. Dieser erzeugt den Mapping-Code bereits zur Entwicklungszeit, sodass keine Laufzeitcodegenerierung notwendig ist. Der JSON-Source-Generator war (und ist) ein wichtiges Instrument fĂĽr die Leistungsoptimierung.
Mit Ausdehnung des Native-AOT-Compilers auf ASP.NET Core Web APIs ist er aber nochmals wichtiger geworden, denn bei Native AOT ist keine Laufzeitkompilierung möglich.
Der JSON-Source-Generator bietet in System.Text.Json
Version 8.0 folgende neuen Möglichkeiten:
- Der Source Generator fĂĽr JSON (
Text.Json.SourceGeneration.JsonSourceGenerator
) unterstützt nun auch die in C# 9.0 eingeführten Init-Only-Properties und die in C# 11.0 eingeführten Required Properties. - Entwickler können per Projekteinstellung dafür sorgen, dass
System.Text.Json
gar keine Laufzeitcodegenerierung mehr ausfĂĽhrt:<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
- Entwickler können im Programmcode mit einem statischen Mitglied abfragen, ob eine Laufzeitcodegenerierung möglich ist:
IsReflectionEnabledByDefault
- Zu den Neuerungen in
System.Text.Json
8.0 gehört auch, dass die Annotation[JsonSourceGenerationOptions]
nun alle Optionen bietet, die auch die KlasseJsonSerializerOptions
beim imperativen Programmieren mit der KlasseText.Json. JsonSerializer
erlaubt.
Wenn die Laufzeitcodegenerierung im JSON-Serializer abgeschaltet ist, man aber dennoch eine Serialisierung ohne Source Generator versucht (etwa JsonSerializer.Serialize(new { value = 42 });
), kassiert man folgende Fehlermeldung: "Reflection-based serialization has been disabled for this application. Either use the source generator APIs or explicitly configure the 'JsonSerializerOptions.TypeInfoResolver' property."
Wenn die Laufzeitcodegenerierung im JSON-Serializer abgeschaltet ist, muss man eine von JsonSerializerContext
abgeleitete Klasse erschaffen, die per Annotation [JsonSerializable]
die Verweise auf die zu (de)serialisierenden .NET-Klassen erhält. Optional kann man die Einstellung per [JsonSourceGenerationOptions]
vornehmen.
In der Online-Konferenz betterCode() .NET 9.0 am 19. November 2024 von iX und dpunkt.verlag präsentieren .NET-Experten von www.IT-Visions.de den fertigen Stand von .NET 9.0 anhand von Praxisbeispielen. Dazu zählen die Neuerungen in .NET 9.0 SDK, C# 13.0, ASP.NET Core 9.0, Blazor 9.0, Windows Forms 9.0, WPF 9.0, WinUI, .NET MAUI 9.0 und die Integration von Künstlicher Intelligenz in .NET-Anwendungen. Das Programm bietet sechs Vorträge, eine Diskussion und sechs Workshops.
Tickets sind zum Frühbucherpreis erhältlich.
Die im folgenden Code verwendeten Klassen Consultant
und Person
waren bereits im Beispielcode zum vorherigen Teil der Serie:
[JsonSerializable(typeof(Address))]
[JsonSerializable(typeof(Person))]
[JsonSerializable(typeof(Consultant))]
[JsonSourceGenerationOptions(PreferredObjectCreationHandling
=JsonObjectCreationHandling.Populate)]
internal partial class PersonJsonContext : JsonSerializerContext
{
}
Diese Klasse muss man dann in den Serialisierungsoptionen festlegen:
var options = new JsonSerializerOptions
{
TypeInfoResolver = PersonJsonContext.Default
};
Das folgende Listing zeigt, dass in System.Text.Json
nun ein erforderliches Mitglied, das beim Deserialisieren nicht befĂĽllt wird, auch bei JSON-Source-Generator zum Laufzeitfehler fĂĽhrt.
try
{
var jsonString = """
{"FULL-NAME":"Holger Schwichtenberg","PERSONAL-WEBSITE":"www.dotnet-doktor.de"}
""";
Console.WriteLine("JSON: " + jsonString);
var obj = JsonSerializer.Deserialize<Consultant>(jsonString, options);
if (obj != null) CUI.Success(obj.ToString());
}
catch (Exception ex)
{
CUI.PrintError(ex.Message); // JSON deserialization for type 'NET8Konsole.Consultant' was missing required properties, including the following: ID !!! Vor .NET 8.0 wäre hier in Verbindung mit Source Generator KEIN Laufzeitfehler aufgetreten. ID war = 0
}
(rme)