Delen via


Null-aantekeningen respecteren

Vanaf .NET 9 JsonSerializer heeft (beperkte) ondersteuning voor niet-nullable verwijzingstypen afdwingen in zowel serialisatie als deserialisatie. U kunt deze ondersteuning in-/uitschakelen met behulp van de JsonSerializerOptions.RespectNullableAnnotations vlag.

Het volgende codefragment genereert bijvoorbeeld een JsonException tijdens serialisatie met een bericht als volgt:

De eigenschap of het veld 'Naam' voor het type 'Persoon' staat het ophalen van null-waarden niet toe. Overweeg de aantekening van de null-waarde bij te werken.

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

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

    record Person(string Name);

Op dezelfde manier RespectNullableAnnotations wordt null-baarheid afgedwongen bij deserialisatie. Het volgende codefragment genereert een JsonException tijdens serialisatie met een bericht zoals:

De constructorparameter 'Naam' voor het type 'Persoon' staat geen null-waarden toe. Overweeg de aantekening van de null-waarde bij te werken.

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

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

    record Person(string Name);

Tip

Beperkingen

Vanwege de implementatie van niet-null-referentietypen heeft deze functie enkele belangrijke beperkingen. Raak vertrouwd met deze beperkingen voordat u de functie inschakelt. De hoofdmap van het probleem is dat verwijzingstype nullability geen eersteklas representatie heeft in de tussenliggende taal (IL). Als zodanig zijn de expressies MyPoco en MyPoco? zijn ze niet te onderscheiden vanuit het perspectief van runtime-reflectie. Hoewel de compiler ervoor probeert te zorgen door kenmerkmetagegevens te verzenden (zie sharplab.io voorbeeld), zijn deze metagegevens beperkt tot niet-algemene lidaantekeningen die zijn gericht op een bepaalde typedefinitie. Deze beperking is de reden dat de vlag alleen null-annotaties valideert die aanwezig zijn op niet-algemene eigenschappen, velden en constructorparameters. System.Text.Json biedt geen ondersteuning voor afdwinging van null-waarden voor:

  • Typen op het hoogste niveau of het type dat wordt doorgegeven bij het maken van de eerste JsonSerializer.Deserialize() of JsonSerializer.Serialize() aanroep.
  • Typen verzamelingselementen, bijvoorbeeld de List<string> typen en List<string?> typen zijn niet te onderscheiden.
  • Eigenschappen, velden of constructorparameters die algemeen zijn.

Als u in deze gevallen null-afdwinging wilt toevoegen, modelleert u uw type als een struct (omdat ze geen null-waarden toelaten) of maakt u een aangepast conversieprogramma dat de eigenschap overschrijft HandleNull aan true.

Functieschakelaar

U kunt de RespectNullableAnnotations instelling globaal inschakelen met behulp van de System.Text.Json.Serialization.RespectNullableAnnotationsDefault functieschakelaar. Voeg het volgende MSBuild-item toe aan uw projectbestand (bijvoorbeeld .csproj-bestand ):

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

De RespectNullableAnnotationsDefault API is geïmplementeerd als een opt-in-vlag in .NET 9 om te voorkomen dat bestaande toepassingen worden onderbroken. Als u een nieuwe toepassing schrijft, is het raadzaam deze vlag in te schakelen in uw code.

Relatie tussen nullable en optionele parameters

RespectNullableAnnotations breidt afdwinging niet uit naar niet-opgegeven JSON-waarden, omdat System.Text.Json vereiste en niet-nullbare eigenschappen worden behandeld als orthogonale concepten. Het volgende codefragment genereert bijvoorbeeld geen uitzondering tijdens deserialisatie:

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; }
}

Dit gedrag komt voort uit de C#-taal zelf, waar u vereiste eigenschappen kunt hebben die nullable zijn:

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

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

En u kunt ook optionele eigenschappen hebben die niet nullable zijn:

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

Dezelfde orthogonaliteit is van toepassing op constructorparameters:

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

Zie ook