Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
À partir de .NET 9, JsonSerializer offre un support limité pour l’application des types de référence non nullables dans la sérialisation et la désérialisation. Vous pouvez activer ou désactiver ce support à l’aide de l’indicateur JsonSerializerOptions.RespectNullableAnnotations.
Par exemple, l’extrait de code suivant déclenche une JsonException pendant la sérialisation avec un message comme :
La propriété ou le champ « Name » du type « Person » n’autorise pas les valeurs nulles. Envisagez de mettre à jour son annotation de nullabilité.
public static void RunIt()
{
#nullable enable
JsonSerializerOptions options = new()
{
RespectNullableAnnotations = true
};
Person invalidValue = new(Name: null!);
JsonSerializer.Serialize(invalidValue, options);
}
record Person(string Name);
De même, RespectNullableAnnotations applique la nullabilité lors de la désérialisation. L’extrait de code suivant déclenche une JsonException pendant la sérialisation avec un message comme :
Le paramètre de constructeur « Name » du type « Person » n’autorise pas les valeurs nulles. Envisagez de mettre à jour son annotation de nullabilité.
public static void RunIt()
{
#nullable enable
JsonSerializerOptions options = new()
{
RespectNullableAnnotations = true
};
string json = """{"Name":null}""";
JsonSerializer.Deserialize<Person>(json, options);
}
record Person(string Name);
Conseil
- Vous pouvez configurer la nullabilité au niveau individuel des propriétés à l’aide des propriétés IsGetNullable et IsSetNullable.
- Le compilateur C# utilise les attributs
[NotNull],[AllowNull],[MaybeNull]et[DisallowNull]pour affiner les annotations dans les accesseurs (getters et setters). Ces attributs sont également reconnus par cette fonctionnalité System.Text.Json. (Pour plus d’informations sur les attributs, consultez Attributs pour l’analyse statique de l’état de nullabilité.)
Limites
En raison de la façon dont les types de référence non nullables sont implémentés, cette fonctionnalité présente des limitations importantes. Familiarisez-vous avec ces limitations avant d’activer la fonctionnalité. Le problème fondamental est que la nullabilité des types de référence n’a pas de représentation de premier ordre dans le langage intermédiaire (IL). Par conséquent, les expressions MyPoco et MyPoco? sont indistinguishables du point de vue de la réflexion du runtime. Bien que le compilateur tente de compenser cela en émettant des métadonnées d’attributs (voir l’exemple sur sharplab.io), ces métadonnées sont limitées aux annotations des membres non génériques qui sont liées à une définition de type spécifique. Cette limitation explique pourquoi l’indicateur ne valide que les annotations de nullabilité présentes sur les propriétés, champs et paramètres de constructeur non génériques.
System.Text.Json ne prend pas en charge l’application de la nullabilité sur :
- Les types de premier niveau, ou le type passé lors du premier appel à
JsonSerializer.Deserialize()ouJsonSerializer.Serialize(). - Les types d’éléments de collection, comme les types
List<string>etList<string?>, sont indiscernables. - Les propriétés, champs ou paramètres de constructeur génériques.
Si vous souhaitez ajouter une application de la nullabilité dans ces cas, modélisez votre type comme une structure (puisqu’elles n’admettent pas les valeurs nulles) ou créez un convertisseur personnalisé qui remplace sa propriété HandleNull par true.
Commutateur de fonctionnalité
Vous pouvez activer l’option RespectNullableAnnotations globalement en utilisant le commutateur de fonctionnalité System.Text.Json.Serialization.RespectNullableAnnotationsDefault. Ajoutez l’élément MSBuild suivant à votre fichier de projet (par exemple, le fichier .csproj) :
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Text.Json.Serialization.RespectNullableAnnotationsDefault" Value="true" />
</ItemGroup>
L’API RespectNullableAnnotationsDefault a été implémentée comme un indicateur activable dans .NET 9 pour éviter de rompre les applications existantes. Si vous écrivez une nouvelle application, il est fortement recommandé d’activer cet indicateur dans votre code.
Relation entre les paramètres nullable et optionnels
RespectNullableAnnotations n’étend pas l’application aux valeurs JSON non spécifiées, car System.Text.Json traite les propriétés requises et non nullables comme des concepts orthogonaux. Par exemple, l’extrait de code suivant ne déclenche pas d’exception lors de la désérialisation :
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; }
}
Ce comportement provient du langage C# lui-même, où vous pouvez avoir des propriétés requises qui sont nullables :
MyPoco poco = new() { Value = null }; // No compiler warnings.
class MyPoco
{
public required string? Value { get; set; }
}
Et vous pouvez également avoir des propriétés optionnelles qui ne sont pas nullables :
class MyPoco
{
public string Value { get; set; } = "default";
}
La même orthogonalité s’applique aux paramètres de constructeur :
record MyPoco(
string RequiredNonNullable,
string? RequiredNullable,
string OptionalNonNullable = "default",
string? OptionalNullable = "default"
);
Valeurs manquantes et valeurs Null
Il est important de comprendre la distinction entre les propriétés JSON manquantes et les propriétés avec des valeurs explicites null lorsque vous définissez RespectNullableAnnotations. JavaScript fait la distinction entre undefined (propriété manquante) et null (valeur null explicite). Toutefois, .NET n’a pas undefined de concept, donc les deux cas se désérialisent en null dans .NET.
Lors de la désérialisation, quand RespectNullableAnnotations est true:
Une valeur null explicite lève une exception pour les propriétés non nullables. Par exemple,
{"Name":null}lève une exception lors de la désérialisation vers une propriété non nullablestring Name.Une propriété manquante ne lève pas d’exception, même pour les propriétés non nullables. Par exemple,
{}ne lève pas d’exception lors de la désérialisation vers une propriété non nullablestring Name. Le sérialiseur ne définit pas la propriété, laissant la valeur définie par défaut par le constructeur. Pour un type de référence non nullable non initialisé, cela entraînenull, ce qui déclenche un avertissement du compilateur.Le code suivant montre comment une propriété manquante ne lève pas d’exception pendant la désérialisation :
public static void RunIt() { #nullable enable JsonSerializerOptions options = new() { RespectNullableAnnotations = true }; // Missing property - does NOT throw an exception. string jsonMissing = """{}"""; var resultMissing = JsonSerializer.Deserialize<Person>(jsonMissing, options); Console.WriteLine(resultMissing.Name is null); // True. } record Person(string Name);
Cette différence de comportement se produit parce que les propriétés manquantes sont traitées comme facultatives (non fournies), tandis que les valeurs explicites null sont traitées comme des valeurs fournies qui violent la contrainte non nullable. Si vous devez imposer qu'une propriété soit présente dans le JSON, utilisez le required modificateur ou configurez la propriété comme requise à l’aide de JsonRequiredAttribute ou du modèle de contrats.