null 許容注釈を考慮する
.NET 9 以降では、JsonSerializer は、シリアル化とデシリアル化の両方で、null 非許容参照型の強制を (限定的に) サポートします。 JsonSerializerOptions.RespectNullableAnnotations フラグを使用して、このサポートを切り替えることができます。
たとえば、次のコード スニペットは、次のようなメッセージを含むシリアル化中に JsonException をスローします。
型 'Person' のプロパティまたはフィールド 'Name' では、null 値を取得できません。 null 許容注釈を更新することを検討してください。
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 は逆シリアル化に null 許容を適用します。 次のコード スニペットは、次のようなメッセージを含むシリアル化中に JsonException をスローします。
型 'Person' のコンストラクター パラメーター 'Name' は null 値を許可しません。 null 許容注釈を更新することを検討してください。
public static void RunIt()
{
#nullable enable
JsonSerializerOptions options = new()
{
RespectNullableAnnotations = true
};
string json = """{"Name":null}""";
JsonSerializer.Deserialize<Person>(json, options);
}
record Person(string Name);
ヒント
- IsGetNullable プロパティと IsSetNullable プロパティを使用して、個々のプロパティ レベルで null 許容を構成できます。
- C# コンパイラでは、
[NotNull]
、[AllowNull]
、[MaybeNull]
、および[DisallowNull]
属性を使用して、getter と setter の注釈を微調整します。 これらの属性も、この System.Text.Json 機能によって認識されます。 (属性の詳細については、「null 状態スタティック分析」を参照してください。
制限事項
null 非許容参照型の実装方法により、この機能にはいくつかの重要な制限があります。 この機能を有効にする前に、これらの制限事項を理解しておいてください。 この問題の根本は、参照型の null 許容に中間言語 (IL) でのファースト クラス表現が存在しないということです。 そのため、式 MyPoco
および MyPoco?
は、実行時リフレクションの観点からは区別できません。 コンパイラは属性メタデータ ( sharplab.io 例 を参照) を生成することによってこれを構成しようとしますが、このメタデータは、特定の型定義をスコープとする非ジェネリック メンバー注釈に制限されます。 この制限は、フラグが非ジェネリック プロパティ、フィールド、およびコンストラクター パラメーターに存在する null 許容注釈のみを検証する理由です。 System.Text.Json では、次に対する null 許容の適用はサポートされていません。
- 最上位レベルの型、または最初の
JsonSerializer.Deserialize()
またはJsonSerializer.Serialize()
呼び出しを行うときに渡される型。 - コレクション要素の型 (たとえば、
List<string>
型とList<string?>
型は区別できません)。 - ジェネリックであるプロパティ、フィールド、またはコンストラクター パラメーター。
このような場合に null 許容の適用を追加する場合は、型を構造体としてモデル化するか (null 値を許可しないため)、その HandleNull プロパティを true
にオーバーライドするカスタム コンバーターを作成します。
機能スイッチ
この設定は、System.Text.Json.Serialization.RespectNullableAnnotationsDefault
機能スイッチを使用して RespectNullableAnnotations
をグローバルに有効にすることができます。 次の MSBuild 項目をプロジェクト ファイル (たとえば、.csproj ファイルなど) に追加します。
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Text.Json.Serialization.RespectNullableAnnotationsDefault" Value="true" />
</ItemGroup>
RespectNullableAnnotationsDefault
API は、既存のアプリケーションの中断を回避するために、.NET 9 でオプトイン フラグとして実装されました。 新しいアプリケーションを作成する場合は、コードでこのフラグを有効にすることを強くお勧めします。
null 許容パラメーターと省略可能パラメーターの関係
System.Text.Json は、必須プロパティと null 非許容プロパティを直交概念として扱うため、RespectNullableAnnotations 適用を未指定の JSON 値に拡張しません。 たとえば、次のコード スニペットでは、逆シリアル化中に例外がスローされません。
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; }
}
この動作は C# 言語自体に由来し、null 許容の必須プロパティを持つことができます。
MyPoco poco = new() { Value = null }; // No compiler warnings.
class MyPoco
{
public required string? Value { get; set; }
}
また、null 非許容の省略可能なプロパティを持つこともできます。
class MyPoco
{
public string Value { get; set; } = "default";
}
コンストラクター パラメーターにも同じ直交性が適用されます。
record MyPoco(
string RequiredNonNullable,
string? RequiredNullable,
string OptionalNonNullable = "default",
string? OptionalNullable = "default"
);
関連項目
.NET