Freigeben über


Nullable-Anmerkungen berücksichtigen

Ab .NET 9 bietet JsonSerializer eingeschränkte Unterstützung für die Erzwingung von Verweistypen, die sowohl bei der Serialisierung als auch bei der Deserialisierung keine NULL-Werte zulassen. Sie können diese Unterstützung mit dem Flag JsonSerializerOptions.RespectNullableAnnotations umschalten.

So löst der folgende Codeausschnitt beispielsweise während der Serialisierung eine JsonException mit der folgenden Nachricht aus:

Die Eigenschaft oder das Feld „Name“ des Typs „Person“ lässt das Abrufen von NULL-Werten nicht zu. Erwägen Sie die Aktualisierung der Anmerkung, die Nullwerte zulässt.

    public static void RunIt()
    {
#nullable enable
        JsonSerializerOptions options = new()
        {
            RespectNullableAnnotations = true
        };

        Person invalidValue = new(Name: null!);
        JsonSerializer.Serialize(invalidValue, options);
    }

    record Person(string Name);

Ebenso erzwingt RespectNullableAnnotations Nullwerte bei der Deserialisierung. Der folgende Codeausschnitt löst während der Serialisierung eine JsonException mit der folgenden Nachricht aus:

Der Konstruktorparameter „Name“ für den Typ „Person“ lässt keine NULL-Werte zu. Erwägen Sie die Aktualisierung der Anmerkung, die Nullwerte zulässt.

    public static void RunIt()
    {
#nullable enable
        JsonSerializerOptions options = new()
        {
            RespectNullableAnnotations = true
        };

        string json = """{"Name":null}""";
        JsonSerializer.Deserialize<Person>(json, options);
    }

    record Person(string Name);

Tipp

Begrenzungen

Aufgrund der Implementierung von Verweistypen, die keine NULL-Werte zulassen, enthält dieses Feature einige wichtige Einschränkungen. Machen Sie sich mit diesen Einschränkungen vertraut, bevor Sie das Feature aktivieren. Die Ursache für das Problem liegt darin, dass der Verweistyp, der keine NULL-Werte zulässt, in der Zwischensprache (Intermediate Language, IL) keine erstklassige Darstellung aufweist. Daher lassen sich die Ausdrücke MyPoco und MyPoco? aus der Perspektive der Laufzeitreflexion nicht voneinander unterscheiden. Während der Compiler versucht, dies durch das Ausstellen von Attributmetadaten (siehe sharplab.io-Beispiel) auszugleichen, sind diese Metadaten auf nicht generische Anmerkungen zu Elementen beschränkt, die auf eine bestimmte Typdefinition beschränkt sind. Aufgrund dieser Einschränkung überprüft das Flag nur Anmerkungen zur NULL-Zulässigkeit, die für nicht generische Eigenschaften, Felder und Konstruktorparameter vorhanden sind. System.Text.Json unterstützt nicht die NULL-Zulässigkeit für:

  • Typen auf der obersten Ebene oder den Typ, der beim ersten JsonSerializer.Deserialize() oder JsonSerializer.Serialize() Aufruf übergeben wird.
  • Sammlungselementtypen, z. B. die Typen List<string> und List<string?>, lassen sich nicht voneinander unterscheiden.
  • Alle generischen Eigenschaften, Felder oder Konstruktorparameter.

Wenn Sie in diesem Fall die Erzwingung der NULL-Zulässigkeit hinzufügen möchten, können Sie Ihren Typ entweder als Struktur modellieren (da sie keine NULL-Werte zulässt), oder einen benutzerdefinierten Konverter erstellen, der seine HandleNull-Eigenschaft true überschreibt.

Funktionsschalter

Sie können die Einstellung RespectNullableAnnotations mithilfe des Funktionsschalters System.Text.Json.Serialization.RespectNullableAnnotationsDefault aktivieren. Fügen Sie der Projektdatei das folgende MSBuild-Element hinzu (z. B. .csproj-Datei):

<ItemGroup>
  <RuntimeHostConfigurationOption Include="System.Text.Json.Serialization.RespectNullableAnnotationsDefault" Value="true" />
</ItemGroup>

Die RespectNullableAnnotationsDefault-API wurde als Opt-In-Flag in .NET 9 implementiert, um zu vermeiden, dass vorhandene Anwendungen unterbrochen werden. Wenn Sie eine neue Anwendung schreiben, wird dringend empfohlen, dieses Flag in Ihrem Code zu aktivieren.

Beziehung zwischen Nullable- und optionalen Parametern

RespectNullableAnnotations erweitert die Erzwingung nicht auf nicht angegebene JSON-Werte, da System.Text.Json erforderliche und Non-Nullable-Eigenschaften als orthogonale Konzepte behandelt werden. So löst der folgende Codeausschnitt während der Deserialisierung beispielsweise keine Ausnahme aus:

public static void RunIt()
{
    JsonSerializerOptions options = new()
    {
        RespectNullableAnnotations = true
    };
    var result = JsonSerializer.Deserialize<MyPoco>("{}", options);
    Console.WriteLine(result.Name is null); // True.
}

class MyPoco
{
    public string Name { get; set; }
}

Dieses Verhalten stammt aus der C#-Sprache selbst, die erforderliche, NULL-Werte zulassende Eigenschaften aufweist:

MyPoco poco = new() { Value = null }; // No compiler warnings.

class MyPoco
{
    public required string? Value { get; set; }
}

Außerdem können Sie optionale Eigenschaften haben, die keine NULL-Werte zulassen:

class MyPoco
{
    public string Value { get; set; } = "default";
}

Die gleiche Orthogonalität gilt für Konstruktorparameter:

record MyPoco(
    string RequiredNonNullable,
    string? RequiredNullable,
    string OptionalNonNullable = "default",
    string? OptionalNullable = "default"
    );

Siehe auch