尊重可為 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);
提示
- 您可以使用 和 IsSetNullable 屬性,在個別屬性層級IsGetNullable設定可為 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 和選擇性參數之間的關聯性
RespectNullableAnnotations 不會將強制執行延伸至未指定的 JSON 值,因為 System.Text.Json 會將必要和不可為 Null 的屬性視為正交概念。 例如,下列代碼段不會在還原串行化期間擲回例外狀況:
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"
);