Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Mulai dari .NET 9, JsonSerializer memiliki dukungan (terbatas) untuk penerapan tipe referensi yang tidak dapat bernilai null dalam serialisasi dan deserialisasi. Anda dapat mengalihkan dukungan ini menggunakan JsonSerializerOptions.RespectNullableAnnotations flag.
Misalnya, cuplikan kode berikut melempar JsonException selama serialisasi dengan pesan seperti:
Properti atau bidang 'Nama' pada tipe 'Orang' tidak memperbolehkan mendapatkan nilai null. Pertimbangkan untuk memperbarui anotasi nullability-nya.
public static void RunIt()
{
#nullable enable
JsonSerializerOptions options = new()
{
RespectNullableAnnotations = true
};
Person invalidValue = new(Name: null!);
JsonSerializer.Serialize(invalidValue, options);
}
record Person(string Name);
Demikian pula, RespectNullableAnnotations menerapkan nullability pada deserialisasi. Cuplikan kode berikut melempar JsonException selama serialisasi dengan pesan seperti:
Parameter konstruktor 'Nama' pada jenis 'Orang' tidak mengizinkan nilai null. Pertimbangkan untuk memperbarui anotasi nullability-nya.
public static void RunIt()
{
#nullable enable
JsonSerializerOptions options = new()
{
RespectNullableAnnotations = true
};
string json = """{"Name":null}""";
JsonSerializer.Deserialize<Person>(json, options);
}
record Person(string Name);
Petunjuk / Saran
- Anda dapat mengonfigurasi nullability pada tingkat properti individual menggunakan properti IsGetNullable dan properti IsSetNullable.
- Pengompilasi C# menggunakan atribut
[NotNull],[AllowNull],[MaybeNull], dan[DisallowNull]untuk menyempurnakan anotasi dalam getter dan setter. Atribut ini juga dikenali oleh fitur ini System.Text.Json . (Untuk informasi selengkapnya tentang atribut, lihat Atribut untuk analisis statis status null-state.)
Batasan
Karena bagaimana jenis referensi yang tidak dapat diubah ke null diimplementasikan, fitur ini dilengkapi dengan beberapa batasan penting. Biasakan diri Anda dengan batasan ini sebelum mengaktifkan fitur. Akar masalahnya adalah bahwa jenis referensi nullability tidak memiliki representasi utama dalam bahasa perantara (IL). Dengan demikian, ekspresi MyPoco dan MyPoco? tidak dapat dibedakan dari perspektif refleksi runtime. Ketika kompilator mencoba menebusnya dengan menghasilkan metadata atribut (lihat contoh sharplab.io), metadata ini terbatas pada anotasi anggota non-generik yang hanya mencakup definisi jenis tertentu. Batasan ini adalah alasan bahwa bendera hanya memvalidasi anotasi nullability yang ada pada properti non-generik, bidang, dan parameter konstruktor.
System.Text.Json tidak mendukung penerapan pengawasan nullability pada:
- Jenis tingkat atas, atau jenis yang diteruskan saat melakukan panggilan
JsonSerializer.Deserialize()atauJsonSerializer.Serialize()pertama. - Jenis elemen koleksi—misalnya, jenis
List<string>danList<string?>tidak dapat dibedakan. - Setiap properti, bidang, atau parameter konstruktor yang umum.
Jika Anda ingin menambahkan penegakan nullability dalam kasus ini, ubah jenis Anda menjadi struct (karena mereka tidak menerima nilai null), atau tulis pengonversi kustom yang mengganti propertinya dari HandleNull ke true.
Tombol fitur
Anda dapat mengaktifkan RespectNullableAnnotations pengaturan secara global menggunakan fitur sakelar System.Text.Json.Serialization.RespectNullableAnnotationsDefault. Tambahkan item MSBuild berikut ke file proyek Anda (misalnya, file .csproj ):
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Text.Json.Serialization.RespectNullableAnnotationsDefault" Value="true" />
</ItemGroup>
API RespectNullableAnnotationsDefault diterapkan sebagai opsi keikutsertaan di .NET 9 untuk menghindari gangguan pada aplikasi yang sudah ada. Jika Anda menulis aplikasi baru, sangat disarankan agar Anda mengaktifkan bendera ini dalam kode Anda.
Hubungan antara parameter nullable dan opsional
RespectNullableAnnotations tidak memperluas penegakan ke nilai JSON yang tidak ditentukan, karena System.Text.Json memperlakukan properti yang diperlukan dan tidak dapat diubah ke null sebagai konsep ortogonal. Misalnya, cuplikan kode berikut tidak memberikan pengecualian selama deserialisasi:
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; }
}
Perilaku ini berasal dari bahasa C# itu sendiri, di mana Anda dapat memiliki properti yang diperlukan yang nullable:
MyPoco poco = new() { Value = null }; // No compiler warnings.
class MyPoco
{
public required string? Value { get; set; }
}
Dan Anda juga dapat memiliki properti opsional yang tidak dapat diubah ke null:
class MyPoco
{
public string Value { get; set; } = "default";
}
Orthogonalitas yang sama berlaku untuk parameter konstruktor:
record MyPoco(
string RequiredNonNullable,
string? RequiredNullable,
string OptionalNonNullable = "default",
string? OptionalNullable = "default"
);
Nilai yang hilang versus nilai null
Penting untuk memahami perbedaan antara properti JSON yang hilang dan properti dengan nilai eksplisit null saat Anda mengatur RespectNullableAnnotations. JavaScript membedakan antara undefined (properti yang hilang) dan null (nilai null eksplisit). Namun, .NET tidak memiliki konsep undefined, jadi kedua kasus mendeserialisasikan ke null dalam .NET.
Selama deserialisasi, saat RespectNullableAnnotations adalah true:
Nilai null eksplisit memunculkan pengecualian untuk properti yang tidak dapat diubah ke null. Misalnya,
{"Name":null}menghasilkan pengecualian ketika mendeserialisasi ke propertistring Nameyang tidak dapat bernilai null.Properti yang hilang tidak memberikan pengecualian, bahkan untuk properti yang tidak dapat diubah ke null. Misalnya,
{}tidak melempar pengecualian saat deserialisasi ke propertistring Nameyang tidak dapat null. Serializer tidak mengatur properti, membiarkannya pada nilai default dari konstruktor. Untuk jenis referensi yang tidak dapat diinisialisasi yang tidak dapat diubah ke null, ini menghasilkannull, yang memicu peringatan kompilator.Kode berikut menunjukkan bagaimana properti yang hilang TIDAK melemparkan pengecualian selama deserialisasi:
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);
Perbedaan perilaku ini terjadi karena properti yang hilang diperlakukan sebagai opsional (tidak disediakan), sementara nilai eksplisit null diperlakukan sebagai nilai yang disediakan yang melanggar batasan yang tidak dapat diubah ke null. Jika Anda perlu memberlakukan bahwa properti harus ada di JSON, gunakan pengubah required atau konfigurasikan properti sesuai kebutuhan menggunakan JsonRequiredAttribute atau model kontrak.