次の方法で共有


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

ヒント

制限事項

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"
    );

関連項目