Respektera null-anteckningar
Från och med .NET 9 JsonSerializer har (begränsat) stöd för icke-nullbar referenstypsframtvingande i både serialisering och deserialisering. Du kan växla det här stödet med hjälp av JsonSerializerOptions.RespectNullableAnnotations flaggan.
Följande kodfragment genererar till exempel ett JsonException under serialisering med ett meddelande som:
Egenskapen eller fältet Namn på typen Person tillåter inte att null-värden hämtas. Överväg att uppdatera dess ogiltighetsanteckning.
public static void RunIt()
{
#nullable enable
JsonSerializerOptions options = new()
{
RespectNullableAnnotations = true
};
Person invalidValue = new(Name: null!);
JsonSerializer.Serialize(invalidValue, options);
}
record Person(string Name);
RespectNullableAnnotations På samma sätt framtvingar nullabilitet vid deserialisering. Följande kodfragment genererar ett JsonException under serialisering med ett meddelande som:
Konstruktorparametern "Name" för typen "Person" tillåter inte null-värden. Överväg att uppdatera dess ogiltighetsanteckning.
public static void RunIt()
{
#nullable enable
JsonSerializerOptions options = new()
{
RespectNullableAnnotations = true
};
string json = """{"Name":null}""";
JsonSerializer.Deserialize<Person>(json, options);
}
record Person(string Name);
Dricks
- Du kan konfigurera nullability på en enskild egenskapsnivå med hjälp av IsGetNullable egenskaperna och IsSetNullable .
- C#-kompilatorn använder attributen
[NotNull]
,[AllowNull]
,[MaybeNull]
och[DisallowNull]
för att finjustera anteckningar i getters och setters. Dessa attribut identifieras också av den här System.Text.Json funktionen. (Mer information om attributen finns iAttribut för statisk analys med null-tillstånd.)
Begränsningar
På grund av hur icke-nullbara referenstyper implementeras kommer den här funktionen med några viktiga begränsningar. Bekanta dig med dessa begränsningar innan du aktiverar funktionen. Roten till problemet är att referenstypen nullability inte har någon förstklassig representation på mellanliggande språk (IL). Därför är uttrycken MyPoco
och MyPoco?
oskiljaktiga ur körningsreflektionens perspektiv. Kompilatorn försöker kompensera för detta genom att generera attributmetadata (se sharplab.io exempel), men dessa metadata är begränsade till icke-generiska medlemskommentarer som är begränsade till en viss typdefinition. Den här begränsningen är orsaken till att flaggan endast validerar nullanoteringar som finns på icke-generiska egenskaper, fält och konstruktorparametrar. System.Text.Json stöder inte tillämpning av nullabilitet på:
- Toppnivåtyper, eller den typ som skickas när du gör det första
JsonSerializer.Deserialize()
ellerJsonSerializer.Serialize()
anropet. - Samlingselementtyper – till exempel kan typerna
List<string>
ochList<string?>
inte skiljas åt. - Alla egenskaper, fält eller konstruktorparametrar som är generiska.
Om du vill lägga till nullability enforcement i dessa fall kan du antingen modellera din typ som en struct (eftersom de inte tar emot null-värden) eller skapa en anpassad konverterare som åsidosätter dess HandleNull egenskap till true
.
Funktionsväxlare
Du kan aktivera inställningen RespectNullableAnnotations
globalt med hjälp av funktionsväxeln System.Text.Json.Serialization.RespectNullableAnnotationsDefault
. Lägg till följande MSBuild-objekt i projektfilen (till exempel .csproj-filen ):
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Text.Json.Serialization.RespectNullableAnnotationsDefault" Value="true" />
</ItemGroup>
API:et RespectNullableAnnotationsDefault
implementerades som en opt-in-flagga i .NET 9 för att undvika att bryta befintliga program. Om du skriver ett nytt program rekommenderar vi starkt att du aktiverar den här flaggan i koden.
Relation mellan null- och valfria parametrar
RespectNullableAnnotations utökar inte tillämpningen till ospecificerade JSON-värden, eftersom System.Text.Json nödvändiga och icke-nullbara egenskaper behandlas som ortogonala begrepp. Följande kodfragment utlöser till exempel inte ett undantag under deserialiseringen:
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; }
}
Det här beteendet beror på själva C#-språket, där du kan ha nödvändiga egenskaper som kan vara null:
MyPoco poco = new() { Value = null }; // No compiler warnings.
class MyPoco
{
public required string? Value { get; set; }
}
Och du kan också ha valfria egenskaper som inte är nullbara:
class MyPoco
{
public string Value { get; set; } = "default";
}
Samma ortogonalitet gäller för konstruktorparametrar:
record MyPoco(
string RequiredNonNullable,
string? RequiredNullable,
string OptionalNonNullable = "default",
string? OptionalNullable = "default"
);