Migrasi dari Newtonsoft.Json ke System.Text.Json
Artikel ini menunjukkan cara memigrasikan dari Newtonsoft.Json ke System.Text.Json.
Namespace System.Text.Json
menyediakan fungsionalitas untuk membuat serialisasi ke dan deserialisasi dari JavaScript Object Notation (JSON). System.Text.Json
Pustaka disertakan dalam runtime untuk .NET Core 3.1 dan versi yang lebih baru. Untuk kerangka kerja target lainnya, instal System.Text.Json paket NuGet. Paket ini mendukung:
- .NET Standard 2.0 dan versi yang lebih baru
- .NET Framework 4.6.2 dan versi yang lebih baru
- .NET Core 2.0, 2.1, dan 2.2
Tip
Anda dapat menggunakan bantuan AI untuk bermigrasi dari Newtonsoft.Json
dengan GitHub Copilot.
System.Text.Json
berfokus terutama pada kepatuhan performa, keamanan, dan standar. Memiliki beberapa perbedaan utama dalam perilaku default dan tidak bertujuan untuk memiliki kesamaan fitur dengan Newtonsoft.Json
. Untuk beberapa skenario, System.Text.Json
saat ini tidak memiliki fungsionalitas bawaan, tetapi ada solusi yang direkomendasikan. Untuk skenario lain, solusinya tidak praktis.
Tim System.Text.Json
berinvestasi dalam menambahkan fitur yang paling sering diminta. Jika aplikasi Anda bergantung pada fitur yang hilang, pertimbangkan untuk mengajukan masalah di repositori dotnet/runtime bahasa umum GitHub untuk mengetahui apakah dukungan untuk skenario Anda dapat ditambahkan.
Sebagian besar artikel ini adalah tentang cara menggunakan JsonSerializer API, tetapi juga mencakup panduan tentang cara menggunakan jenis JsonDocument (yang mewakili Model Objek Dokumen atau DOM), Utf8JsonReader, dan Utf8JsonWriter.
Dalam Visual Basic, Anda tidak dapat menggunakan Utf8JsonReader, yang juga berarti Anda tidak dapat menulis pengonversi kustom. Sebagian besar solusi yang disajikan di sini mengharuskan Anda menulis pengonversi kustom. Anda dapat menulis pengonversi kustom di C# dan mendaftarkannya dalam proyek Visual Basic. Untuk informasi selengkapnya, lihat dukungan (Visual Basic).
Tabel perbedaan
Tabel berikut ini mencantumkan Newtonsoft.Json
fitur dan System.Text.Json
persamaannya. Yang setara termasuk dalam kategori berikut:
- ✔️ Didukung oleh fungsionalitas bawaan. Mendapatkan perilaku
System.Text.Json
serupa mungkin memerlukan penggunaan atribut atau opsi global. - ⚠️ Tidak didukung, tetapi solusi dimungkinkan. Solusinya adalah pengonversi kustom, yang mungkin tidak menyediakan paritas lengkap dengan
Newtonsoft.Json
fungsionalitas. Untuk beberapa di antaranya, kode sampel disediakan sebagai contoh. Jika Anda mengandalkanNewtonsoft.Json
fitur-fitur ini, migrasi akan memerlukan modifikasi pada model objek .NET atau perubahan kode lainnya. - ❌ Tidak didukung, dan solusinya tidak praktis atau mungkin. Jika Anda mengandalkan
Newtonsoft.Json
fitur-fitur ini, migrasi tidak akan memungkinkan tanpa perubahan yang signifikan.
Newtonsoft.Json fitur | System.Text.Json persamaan |
---|---|
Deserialisasi tak peka huruf besar/kecil secara default | ✔️ Pengaturan global PropertyNameCaseInsensitive |
Nama properti camel-case | ✔️ Pengaturan global PropertyNamingPolicy |
Nama properti camel-case | ✔️ Kebijakan penamaan kasus ular |
Pelepasan karakter minimal | ✔️ Pelepasan karakter yang ketat, dapat dikonfigurasi |
NullValueHandling.Ignore pengaturan global |
✔️ Opsi global DefaultIgnoreCondition |
Izinkan komentar | ✔️ Pengaturan global ReadCommentHandling |
Perbolehkan koma berikutnya | ✔️ Pengaturan global AllowTrailingCommas |
Pendaftaran pengonversi kustom | ✔️ Urutan prioritas berbeda |
Kedalaman maksimum default 64, dapat dikonfigurasi | ✔️ Kedalaman maksimum default 64, dapat dikonfigurasi |
PreserveReferencesHandling pengaturan global |
✔️ Pengaturan global ReferenceHandling |
Serialisasi atau deserialisasi angka dalam tanda kutip | ✔️ Pengaturan global NumberHandling, atribut [JsonNumberHandling] |
Deserialisasi ke kelas dan struktur yang tidak dapat diubah | ✔️ JsonConstructor, Rekaman C# 9 |
Dukungan untuk bidang | ✔️ Pengaturan global IncludeFields, atribut [JsonInclude] |
DefaultValueHandling pengaturan global |
✔️ Opsi global DefaultIgnoreCondition |
NullValueHandling pengaturan pada [JsonProperty] |
✔️ Atribut JsonIgnore |
DefaultValueHandling pengaturan pada [JsonProperty] |
✔️ Atribut JsonIgnore |
Deserialisasi Dictionary dengan kunci non-string |
✔️ Didukung |
Dukungan untuk setter dan getter properti non-publik | ✔️ Atribut JsonInclude |
atribut [JsonConstructor] |
✔️ Atribut [JsonConstructor] |
ReferenceLoopHandling pengaturan global |
✔️ Pengaturan global ReferenceHandling |
Panggilan balik | ✔️ Panggilan balik |
Nan, Infinity, -Infinity | ✔️ Didukung |
Required pengaturan pada [JsonProperty] atribut |
✔️ Atribut [JsonRequired] dan pengubah yang diperlukan C# |
DefaultContractResolver mengabaikan properti |
✔️ Kelas DefaultJsonTypeInfoResolver |
Serialisasi polimorfik | ✔️ Atribut [JsonDerivedType] |
Deserialisasi polimorfik | ✔️ Ketik diskriminator pada atribut [JsonDerivedType] |
Deserialisasi nilai enum string | ✔️ Mendeserialisasi nilai enum string |
MissingMemberHandling pengaturan global |
✔️ Menangani anggota yang hilang |
Mengisi properti tanpa setter | ✔️ Mengisi properti tanpa setter |
ObjectCreationHandling pengaturan global |
✔️ Gunakan kembali daripada mengganti properti |
Dukungan untuk berbagai jenis | ⚠️ Beberapa jenis memerlukan pengonversi kustom |
Deserialisasi jenis yang disimpulkan ke object properti |
⚠️ Tidak didukung, solusi, sampel |
Deserialisasi JSON null harfiah ke jenis nilai yang tidak dapat diubah ke null |
⚠️ Tidak didukung, solusi, sampel |
DateTimeZoneHandling , DateFormatString pengaturan |
⚠️ Tidak didukung, solusi, sampel |
metode JsonConvert.PopulateObject |
⚠️ Tidak didukung, solusi |
Dukungan untuk System.Runtime.Serialization atribut |
⚠️ Tidak didukung, solusi, sampel |
JsonObjectAttribute |
⚠️ Tidak didukung, solusi |
Izinkan nama properti tanpa tanda kutip | ❌Tidak didukung oleh desain |
Izinkan tanda kutip tunggal di sekitar nilai string | ❌Tidak didukung oleh desain |
Izinkan nilai JSON non-string untuk properti string | ❌Tidak didukung oleh desain |
TypeNameHandling.All pengaturan global |
❌Tidak didukung oleh desain |
Dukungan untuk JsonPath kueri |
❌Tidak didukung |
Batas yang dapat dikonfigurasi | ❌Tidak didukung |
Newtonsoft.Json fitur | System.Text.Json persamaan |
---|---|
Deserialisasi tak peka huruf besar/kecil secara default | ✔️ Pengaturan global PropertyNameCaseInsensitive |
Nama properti camel-case | ✔️ Pengaturan global PropertyNamingPolicy |
Pelepasan karakter minimal | ✔️ Pelepasan karakter yang ketat, dapat dikonfigurasi |
NullValueHandling.Ignore pengaturan global |
✔️ Opsi global DefaultIgnoreCondition |
Izinkan komentar | ✔️ Pengaturan global ReadCommentHandling |
Perbolehkan koma berikutnya | ✔️ Pengaturan global AllowTrailingCommas |
Pendaftaran pengonversi kustom | ✔️ Urutan prioritas berbeda |
Kedalaman maksimum default 64, dapat dikonfigurasi | ✔️ Kedalaman maksimum default 64, dapat dikonfigurasi |
PreserveReferencesHandling pengaturan global |
✔️ Pengaturan global ReferenceHandling |
Serialisasi atau deserialisasi angka dalam tanda kutip | ✔️ Pengaturan global NumberHandling, atribut [JsonNumberHandling] |
Deserialisasi ke kelas dan struktur yang tidak dapat diubah | ✔️ JsonConstructor, Rekaman C# 9 |
Dukungan untuk bidang | ✔️ Pengaturan global IncludeFields, atribut [JsonInclude] |
DefaultValueHandling pengaturan global |
✔️ Opsi global DefaultIgnoreCondition |
NullValueHandling pengaturan pada [JsonProperty] |
✔️ Atribut JsonIgnore |
DefaultValueHandling pengaturan pada [JsonProperty] |
✔️ Atribut JsonIgnore |
Deserialisasi Dictionary dengan kunci non-string |
✔️ Didukung |
Dukungan untuk setter dan getter properti non-publik | ✔️ Atribut JsonInclude |
atribut [JsonConstructor] |
✔️ Atribut [JsonConstructor] |
ReferenceLoopHandling pengaturan global |
✔️ Pengaturan global ReferenceHandling |
Panggilan balik | ✔️ Panggilan balik |
Nan, Infinity, -Infinity | ✔️ Didukung |
Required pengaturan pada [JsonProperty] atribut |
✔️ Atribut [JsonRequired] dan pengubah yang diperlukan C# |
DefaultContractResolver mengabaikan properti |
✔️ Kelas DefaultJsonTypeInfoResolver |
Serialisasi polimorfik | ✔️ Atribut [JsonDerivedType] |
Deserialisasi polimorfik | ✔️ Ketik diskriminator pada atribut [JsonDerivedType] |
Deserialisasi nilai enum string | ✔️ Mendeserialisasi nilai enum string |
Dukungan untuk berbagai jenis | ⚠️ Beberapa jenis memerlukan pengonversi kustom |
Deserialisasi jenis yang disimpulkan ke object properti |
⚠️ Tidak didukung, solusi, sampel |
Deserialisasi JSON null harfiah ke jenis nilai yang tidak dapat diubah ke null |
⚠️ Tidak didukung, solusi, sampel |
DateTimeZoneHandling , DateFormatString pengaturan |
⚠️ Tidak didukung, solusi, sampel |
metode JsonConvert.PopulateObject |
⚠️ Tidak didukung, solusi |
ObjectCreationHandling pengaturan global |
⚠️ Tidak didukung, solusi |
Tambahkan ke koleksi tanpa setter | ⚠️ Tidak didukung, solusi |
Nama properti camel-case | ⚠️ Tidak didukung, solusi |
Dukungan untuk System.Runtime.Serialization atribut |
⚠️ Tidak didukung, solusi, sampel |
MissingMemberHandling pengaturan global |
⚠️ Tidak didukung, solusi, sampel |
JsonObjectAttribute |
⚠️ Tidak didukung, solusi |
Izinkan nama properti tanpa tanda kutip | ❌Tidak didukung oleh desain |
Izinkan tanda kutip tunggal di sekitar nilai string | ❌Tidak didukung oleh desain |
Izinkan nilai JSON non-string untuk properti string | ❌Tidak didukung oleh desain |
TypeNameHandling.All pengaturan global |
❌Tidak didukung oleh desain |
Dukungan untuk JsonPath kueri |
❌Tidak didukung |
Batas yang dapat dikonfigurasi | ❌Tidak didukung |
Newtonsoft.Json fitur | System.Text.Json persamaan |
---|---|
Deserialisasi tak peka huruf besar/kecil secara default | ✔️ Pengaturan global PropertyNameCaseInsensitive |
Nama properti camel-case | ✔️ Pengaturan global PropertyNamingPolicy |
Pelepasan karakter minimal | ✔️ Pelepasan karakter yang ketat, dapat dikonfigurasi |
NullValueHandling.Ignore pengaturan global |
✔️ Opsi global DefaultIgnoreCondition |
Izinkan komentar | ✔️ Pengaturan global ReadCommentHandling |
Perbolehkan koma berikutnya | ✔️ Pengaturan global AllowTrailingCommas |
Pendaftaran pengonversi kustom | ✔️ Urutan prioritas berbeda |
Kedalaman maksimum default 64, dapat dikonfigurasi | ✔️ Kedalaman maksimum default 64, dapat dikonfigurasi |
PreserveReferencesHandling pengaturan global |
✔️ Pengaturan global ReferenceHandling |
Serialisasi atau deserialisasi angka dalam tanda kutip | ✔️ Pengaturan global NumberHandling, atribut [JsonNumberHandling] |
Deserialisasi ke kelas dan struktur yang tidak dapat diubah | ✔️ JsonConstructor, Rekaman C# 9 |
Dukungan untuk bidang | ✔️ Pengaturan global IncludeFields, atribut [JsonInclude] |
DefaultValueHandling pengaturan global |
✔️ Opsi global DefaultIgnoreCondition |
NullValueHandling pengaturan pada [JsonProperty] |
✔️ Atribut JsonIgnore |
DefaultValueHandling pengaturan pada [JsonProperty] |
✔️ Atribut JsonIgnore |
Deserialisasi Dictionary dengan kunci non-string |
✔️ Didukung |
Dukungan untuk setter dan getter properti non-publik | ✔️ Atribut JsonInclude |
atribut [JsonConstructor] |
✔️ Atribut [JsonConstructor] |
ReferenceLoopHandling pengaturan global |
✔️ Pengaturan global ReferenceHandling |
Panggilan balik | ✔️ Panggilan balik |
Nan, Infinity, -Infinity | ✔️ Didukung |
Deserialisasi nilai enum string | ✔️ Mendeserialisasi nilai enum string |
Dukungan untuk berbagai jenis | ⚠️ Beberapa jenis memerlukan pengonversi kustom |
Serialisasi polimorfik | ⚠️ Tidak didukung, solusi, sampel |
Deserialisasi polimorfik | ⚠️ Tidak didukung, solusi, sampel |
Deserialisasi jenis yang disimpulkan ke object properti |
⚠️ Tidak didukung, solusi, sampel |
Deserialisasi JSON null harfiah ke jenis nilai yang tidak dapat diubah ke null |
⚠️ Tidak didukung, solusi, sampel |
Required pengaturan pada [JsonProperty] atribut |
⚠️ Tidak didukung, solusi, sampel |
DefaultContractResolver mengabaikan properti |
⚠️ Tidak didukung, solusi, sampel |
DateTimeZoneHandling , DateFormatString pengaturan |
⚠️ Tidak didukung, solusi, sampel |
metode JsonConvert.PopulateObject |
⚠️ Tidak didukung, solusi |
ObjectCreationHandling pengaturan global |
⚠️ Tidak didukung, solusi |
Tambahkan ke koleksi tanpa setter | ⚠️ Tidak didukung, solusi |
Nama properti camel-case | ⚠️ Tidak didukung, solusi |
JsonObjectAttribute |
⚠️ Tidak didukung, solusi |
Dukungan untuk System.Runtime.Serialization atribut |
❌Tidak didukung |
MissingMemberHandling pengaturan global |
❌Tidak didukung |
Izinkan nama properti tanpa tanda kutip | ❌Tidak didukung oleh desain |
Izinkan tanda kutip tunggal di sekitar nilai string | ❌Tidak didukung oleh desain |
Izinkan nilai JSON non-string untuk properti string | ❌Tidak didukung oleh desain |
TypeNameHandling.All pengaturan global |
❌Tidak didukung oleh desain |
Dukungan untuk JsonPath kueri |
❌Tidak didukung |
Batas yang dapat dikonfigurasi | ❌Tidak didukung |
Ini bukanlah daftar lengkap Newtonsoft.Json
fitur. Daftar ini mencakup banyak skenario yang telah diminta dalam masalah GitHub atau kiriman StackOverflow. Jika Anda menerapkan solusi untuk salah satu skenario yang tercantum di sini yang saat ini tidak memiliki kode sampel, dan jika Anda ingin membagikan solusi Anda, pilih Halaman ini di bagian Umpan Balik di bagian bawah halaman ini. Hal tersebut membuat masalah dalam dokumentasi repositori GitHub ini dan mencantumkannya pada bagian Umpan Balik di halaman ini juga.
Perbedaan perilaku default
System.Text.Json bersifat ketat secara default dan menghindari tebakan atau interpretasi atas nama pemanggil, menekankan perilaku deterministik. Pustaka sengaja dirancang dengan cara ini demi performa dan keamanan. Newtonsoft.Json
bersifat fleksibel secara default. Perbedaan mendasar dalam desain ini berada di belakang banyak perbedaan spesifik berikut dalam perilaku default.
Deserialisasi yang tidak peka huruf besar/kecil
Selama deserialisasi, Newtonsoft.Json
melakukan pencocokan nama properti tak peka huruf besar/kecil cocok secara default. Defaultnya System.Text.Json adalah peka huruf besar/kecil, yang memberikan performa yang lebih baik karena melakukan kecocokan yang tepat. Untuk informasi tentang cara melakukan pencocokan tak peka huruf besar/kecil, lihat Pencocokan properti yang tidak peka huruf besar/kecil.
Jika Anda menggunakan System.Text.Json
secara tidak langsung dengan menggunakan ASP.NET Core, Anda tidak perlu melakukan apa pun untuk mendapatkan perilaku seperti Newtonsoft.Json
. ASP.NET Core menentukan pengaturan untuk nama properti camel-casing dan pencocokan tidak peka huruf besar/kecil saat menggunakan System.Text.Json
.
ASP.NET Core juga memungkinkan deserialisasi angka yang dikutip secara default.
Pelepasan karakter minimal
Selama serialisasi, Newtonsoft.Json
relatif permisif untuk membiarkan karakter melewatinya tanpa melepaskannya. Artinya, ia tidak menggantinya dengan \uxxxx
di mana xxxx
adalah titik kode karakter. Di mana ia melarikan diri dari mereka, ia melakukannya dengan memancarkan \
sebelum karakter (misalnya, "
menjadi \"
). System.Text.Json lolos dari lebih banyak karakter secara default untuk memberikan perlindungan pertahanan mendalam terhadap scripting lintas situs (XSS) atau serangan penyingkapan informasi dan melakukannya dengan menggunakan urutan enam karakter. System.Text.Json
lolos dari semua karakter non-ASCII secara default, jadi Anda tidak perlu melakukan apa pun jika Anda menggunakan StringEscapeHandling.EscapeNonAscii
pada Newtonsoft.Json
. System.Text.Json
juga lolos dari karakter sensitif HTML, secara default. Untuk informasi tentang cara mengambil alih perilaku default System.Text.Json
, lihat Menyesuaikan pengodean karakter.
Komentar
Selama deserialisasi, Newtonsoft.Json
mengabaikan komentar di JSON secara default. Defaultnya System.Text.Json adalah memberikan pengecualian untuk komentar karena spesifikasi RFC 8259 tidak menyertakannya. Untuk informasi tentang cara mengizinkan komentar, lihat Mengizinkan komentar dan koma berikutnya.
Koma berikutnya
Selama deserialisasi, Newtonsoft.Json
mengabaikan koma berikutnya secara default. Ia juga mengabaikan beberapa koma berikutnya (misalnya, [{"Color":"Red"},{"Color":"Green"},,]
). Defaultnya System.Text.Json adalah memberikan pengecualian untuk komentar karena spesifikasi RFC 8259 tidak menyertakannya. Untuk informasi tentang cara membuat System.Text.Json
menerimanya, lihat Mengizinkan komentar dan koma berikutnya. Tidak ada cara untuk mengizinkan beberapa koma berikutnya.
Prioritas pendaftaran pengonversi
Prioritas pendaftaran Newtonsoft.Json
untuk pengonversi kustom adalah sebagai berikut:
- Atribut pada properti
- Atribut pada jenis
- Koleksi pengonversi
Urutan ini berarti bahwa pengonversi kustom dalam Converters
koleksi ditimpa oleh pengonversi yang terdaftar dengan menerapkan atribut pada tingkat jenis. Kedua pendaftaran tersebut ditimpa oleh atribut di tingkat properti.
Prioritas pendaftaran System.Text.Json untuk pengonversi kustom berbeda:
- Atribut pada properti
- Converters koleksi
- Atribut pada jenis
Perbedaannya di sini adalah bahwa pengonversi kustom dalam Converters
koleksi mengambil alih atribut pada tingkat jenis. Tujuan di balik urutan prioritas ini adalah untuk membuat perubahan run-time mengambil alih pilihan waktu desain. Tidak ada cara untuk mengubah prioritas.
Untuk informasi selengkapnya tentang pendaftaran pengonversi kustom, lihat Mendaftarkan pengonversi kustom.
Kedalaman maksimal
Versi Newtonsoft.Json
terbaru memiliki batas kedalaman maksimum 64 secara default. System.Text.Json juga memiliki batas default 64, dan dapat dikonfigurasi dengan mengatur JsonSerializerOptions.MaxDepth.
Jika Anda menggunakan System.Text.Json
secara tidak langsung dengan menggunakan ASP.NET Core, batas kedalaman maksimum default adalah 32. Nilai default sama dengan yang digunakan untuk pengikatan model dan diatur di kelas JsonOptions.
String JSON (nama properti dan nilai string)
Selama deserialisasi, Newtonsoft.Json
menerima nama properti yang dikelilingi oleh tanda kutip ganda, tanda kutip tunggal, atau tanpa tanda kutip. Ia menerima nilai string yang dikelilingi oleh tanda kutip ganda atau tanda kutip tunggal. Misalnya, Newtonsoft.Json
menerima JSON berikut:
{
"name1": "value",
'name2': "value",
name3: 'value'
}
System.Text.Json
hanya menerima nama properti dan nilai string dalam tanda kutip ganda karena format tersebut diperlukan oleh spesifikasi RFC 8259 dan merupakan satu-satunya format yang dianggap sebagai JSON yang valid.
Nilai yang diapit dalam tanda kutip tunggal menghasilkan JsonException dengan pesan berikut:
''' is an invalid start of a value.
Nilai non-string untuk properti string
Newtonsoft.Json
menerima nilai non-string, seperti angka atau literal true
dan false
, untuk deserialisasi ke properti jenis string. Berikut adalah contoh JSON yang Newtonsoft.Json
berhasil mendeserialisasi ke kelas berikut:
{
"String1": 1,
"String2": true,
"String3": false
}
public class ExampleClass
{
public string String1 { get; set; }
public string String2 { get; set; }
public string String3 { get; set; }
}
System.Text.Json
tidak mendeserialisasi nilai non-string ke dalam properti string. Nilai non-string yang diterima untuk bidang string menghasilkan JsonException dengan pesan berikut:
The JSON value could not be converted to System.String.
Skenario menggunakan JsonSerializer
Beberapa skenario berikut tidak didukung oleh fungsionalitas bawaan, tetapi solusinya memungkinkan. Solusinya adalah pengonversi kustom, yang mungkin tidak menyediakan kesamaan lengkap dengan Newtonsoft.Json
fungsionalitas. Untuk beberapa di antaranya, kode sampel disediakan sebagai contoh. Jika Anda mengandalkan Newtonsoft.Json
fitur-fitur ini, migrasi akan memerlukan modifikasi pada model objek .NET atau perubahan kode lainnya.
Untuk beberapa skenario berikut, solusinya tidak praktis atau memungkinkan. Jika Anda mengandalkan Newtonsoft.Json
fitur-fitur ini, migrasi tidak akan memungkinkan tanpa perubahan yang signifikan.
Izinkan atau tulis angka dalam tanda kutip
Newtonsoft.Json
dapat membuat serialisasi atau mendeserialisasi angka yang diwakili oleh string JSON (dikelilingi oleh tanda kutip). Misalnya, ia dapat menerima: {"DegreesCelsius":"23"}
alih-alih {"DegreesCelsius":23}
. Untuk mengaktifkan perilaku tersebut pada System.Text.Json, atur JsonSerializerOptions.NumberHandling ke WriteAsString atau AllowReadingFromString, atau gunakan atribut [JsonNumberHandling].
Jika Anda menggunakan System.Text.Json
secara tidak langsung dengan menggunakan ASP.NET Core, Anda tidak perlu melakukan apa pun untuk mendapatkan perilaku seperti Newtonsoft.Json
. ASP.NET Core menentukan default web saat menggunakan System.Text.Json
, dan default web memungkinkan angka yang dikutip.
Untuk informasi selengkapnya, lihat Mengizinkan atau menulis angka dalam tanda kutip.
Tentukan konstruktor yang akan digunakan saat deserialisasi
Atribut ini Newtonsoft.Json
[JsonConstructor]
memungkinkan Anda menentukan konstruktor mana yang akan dipanggil saat deserialisasi ke POCO.
System.Text.Json
juga memiliki atribut [JsonConstructor]. Untuk informasi selengkapnya, lihat Jenis dan Rekaman yang Tidak Dapat Diubah.
Mengabaikan properti secara kondisional
Newtonsoft.Json
memiliki beberapa cara untuk mengabaikan properti secara kondisional pada serialisasi atau deserialisasi:
DefaultContractResolver
memungkinkan Anda memilih properti untuk disertakan atau diabaikan, berdasarkan kriteria arbitrer.- Pengaturan
NullValueHandling
danDefaultValueHandling
padaJsonSerializerSettings
memungkinkan Anda menentukan bahwa semua properti nilai null atau nilai default harus diabaikan. - Pengaturan
NullValueHandling
danDefaultValueHandling
pada[JsonProperty]
atribut memungkinkan Anda menentukan properti individual yang harus diabaikan saat diatur ke null atau nilai default.
System.Text.Json menyediakan cara berikut untuk mengabaikan properti atau bidang saat melakukan serialisasi:
- Atribut [JsonIgnore] pada properti menyebabkan properti dihilangkan dari JSON selama serialisasi.
- Opsi global IgnoreReadOnlyProperties memungkinkan Anda mengabaikan semua properti baca-saja.
- Jika Anda menyertakan bidang, JsonSerializerOptions.IgnoreReadOnlyFields opsi global memungkinkan Anda mengabaikan semua bidang baca-saja.
DefaultIgnoreCondition
Opsi global memungkinkan Anda mengabaikan semua properti jenis nilai yang memiliki nilai default, atau mengabaikan semua properti jenis referensi yang memiliki nilai null.
Selain itu, dalam .NET 7 dan versi yang lebih baru, Anda dapat menyesuaikan kontrak JSON untuk mengabaikan properti berdasarkan kriteria arbitrer. Untuk informasi selengkapnya, lihat Kontrak kustom.
Opsi ini tidak memungkinkan Anda mengabaikan properti yang dipilih berdasarkan kriteria arbitrer yang dievaluasi pada waktu proses.
Bidang publik dan non-publik
Newtonsoft.Json
dapat menserialisasi dan mendeserialisasi bidang serta properti.
Pada System.Text.Json, gunakan JsonSerializerOptions.IncludeFields pengaturan global atau [JsonInclude] untuk menyertakan bidang saat melakukan serialisasi atau deserialisasi. Sebagai contoh, lihat Menyertakan bidang.
Mempertahankan referensi objek dan menangani perulangan
Secara default, Newtonsoft.Json
melakukan serialisasi berdasarkan nilai. Misalnya, jika objek berisi dua properti yang berisi referensi ke Person
objek yang sama, nilai Person
dari properti objek tersebut diduplikasi di JSON.
Newtonsoft.Json
memiliki PreserveReferencesHandling
pengaturan yang JsonSerializerSettings
memungkinkan Anda membuat serialisasi berdasarkan referensi:
- Metadata pengidentifikasi ditambahkan ke JSON yang dibuat untuk
Person
objek pertama. - JSON yang dibuat untuk objek kedua
Person
berisi referensi ke pengidentifikasi tersebut alih-alih nilai properti.
Newtonsoft.Json
juga memiliki ReferenceLoopHandling
pengaturan yang memungkinkan Anda mengabaikan referensi melingkar daripada memberikan pengecualian.
Untuk mempertahankan referensi dan menangani referensi melingkar pada System.Text.Json, atur JsonSerializerOptions.ReferenceHandler ke Preserve. Pengaturan ReferenceHandler.Preserve
setara denganPreserveReferencesHandling
= PreserveReferencesHandling.All
pada Newtonsoft.Json
.
Opsi ReferenceHandler.IgnoreCycles
ini memiliki perilaku yang mirip dengan Newtonsoft.JsonReferenceLoopHandling.Ignore
. Salah satu perbedaannya adalah implementasi System.Text.Json menggantikan perulangan referensi dengan null
token JSON alih-alih mengabaikan referensi objek. Untuk informasi lebih lanjut, lihat Abaikan referensi melingkar.
Seperti halnya Newtonsoft.JsonReferenceResolver, kelas System.Text.Json.Serialization.ReferenceResolver menentukan perilaku mempertahankan referensi pada serialisasi dan deserialisasi. Buat kelas turunan untuk menentukan perilaku kustom. Sebagai contoh, lihat GuidReferenceResolver.
Beberapa fitur terkait Newtonsoft.Json
tidak didukung:
Untuk informasi selengkapnya, lihat Mempertahankan referensi dan menangani referensi melingkar.
Kamus dengan kunci non-string
Baik Newtonsoft.Json
dan System.Text.Json
mendukung koleksi jenis Dictionary<TKey, TValue>
. Namun, dalam System.Text.Json
, TKey
harus berupa jenis primitif, bukan jenis kustom. Untuk informasi selengkapnya, lihat Jenis kunci yang didukung.
Perhatian
Deserialisasi ke Dictionary<TKey, TValue>
di mana TKey
berjenis apa pun selain string
dapat menyebabkan kerentanan keamanan dalam aplikasi pemakai. Untuk informasi selengkapnya, lihat dotnet/runtime#4761.
Jenis tanpa dukungan bawaan
System.Text.Json tidak menyediakan dukungan bawaan untuk jenis berikut:
- DataTable dan jenis terkait (untuk informasi selengkapnya, lihat Jenis koleksi yang didukung)
- ExpandoObject
- TimeZoneInfo
- BigInteger
- DBNull
- Type
- ValueTuple dan jenis generiknya yang terkait
Pengonversi kustom dapat diimplementasikan untuk jenis yang tidak memiliki dukungan bawaan.
Serialisasi polimorfik
Newtonsoft.Json
secara otomatis melakukan serialisasi polimorfik. Mulai dari .NET 7, System.Text.Json mendukung serialisasi polimorfik melalui JsonDerivedTypeAttribute atribut . Untuk informasi selengkapnya, lihat Membuat serialisasi properti kelas turunan.
Deserialisasi polimorfik
Newtonsoft.Json
memiliki TypeNameHandling
pengaturan yang menambahkan metadata nama-jenis ke JSON saat melakukan serialisasi. Ia menggunakan metadata saat deserialisasi untuk melakukan deserialisasi polimorfik. Mulai dari .NET 7, System.Text.Json bergantung pada jenis informasi diskriminator untuk melakukan deserialisasi polimorfik. Metadata ini dipancarkan dalam JSON dan kemudian digunakan selama deserialisasi untuk menentukan apakah akan mendeserialisasi ke jenis dasar atau jenis turunan. Untuk informasi selengkapnya, lihat Membuat serialisasi properti kelas turunan.
Untuk mendukung deserialisasi polimorfik dalam versi .NET yang lebih lama, buat pengonversi seperti contoh dalam Cara menulis pengonversi kustom.
Mendeserialisasi nilai enum string
Secara default, System.Text.Json tidak mendukung deserialisasi nilai enum string, sedangkan Newtonsoft.Json
tidak. Misalnya, kode berikut melempar :JsonException
string json = "{ \"Text\": \"Hello\", \"Enum\": \"Two\" }";
var _ = JsonSerializer.Deserialize<MyObj>(json); // Throws exception.
class MyObj
{
public string Text { get; set; } = "";
public MyEnum Enum { get; set; }
}
enum MyEnum
{
One,
Two,
Three
}
Namun, Anda dapat mengaktifkan deserialisasi nilai enum string dengan menggunakan pengonversi JsonStringEnumConverter . Untuk informasi selengkapnya, lihat Enums sebagai string.
Deserialisasi properti objek
Ketika Newtonsoft.Json
deserialisasi ke Object, maka akan:
- Menyimpulkan jenis nilai primitif dalam payload JSON (selain
null
) dan mengembalikanstring
,long
,double
,boolean
, atauDateTime
yang tersimpan sebagai objek yang dikemas. Nilai primitif adalah nilai JSON tunggal seperti angka JSON, string,true
,false
, ataunull
. - Mengembalikan
JObject
atauJArray
untuk nilai kompleks dalam payload JSON. Nilai kompleks adalah kumpulan pasangan kunci-nilai JSON dalam kurung kurawal ({}
) atau daftar nilai dalam tanda kurung siku ([]
). Properti dan nilai dalam kurung kurawal atau kurung siku dapat memiliki properti atau nilai tambahan. - Mengembalikan referensi null saat payload memiliki
null
harfiah JSON.
System.Text.Json menyimpan JsonElement
yang sudah dikemas untuk nilai primitif dan kompleks setiap kali melakukan deserialisasi ke Object, misalnya:
- Sebuah
object
properti. - Sebuah
object
nilai kamus. - Sebuah
object
nilai array. - Akar
object
.
Namun, System.Text.Json
memperlakukan null
sama halnya dengan Newtonsoft.Json
dan mengembalikan referensi null ketika payload memiliki null
harfiah JSON di dalamnya.
Untuk menerapkan inferensi jenis untuk object
properti, buat pengonversi seperti contoh dalam Cara menulis pengonversi kustom.
Deserialisasi null ke tipe yang tidak dapat diubah ke null
Newtonsoft.Json
tidak memberikan pengecualian dalam skenario berikut:
NullValueHandling
diatur keIgnore
, dan- Selama deserialisasi, JSON berisi nilai null untuk jenis nilai yang tidak dapat diubah ke null.
Dalam skenario yang sama, System.Text.Json memang memberikan pengecualian. (Pengaturan penanganan null yang sesuai pada System.Text.Json
adalah JsonSerializerOptions.IgnoreNullValues = true
.)
Jika Anda memiliki jenis target, solusi terbaik adalah membuat properti yang bersangkutan dapat diubah ke null (misalnya, mengubah int
ke int?
).
Solusi lain adalah membuat pengonversi untuk jenis tersebut, seperti contoh berikut yang menangani nilai null untuk DateTimeOffset
jenis:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SystemTextJsonSamples
{
public class DateTimeOffsetNullHandlingConverter : JsonConverter<DateTimeOffset>
{
public override DateTimeOffset Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) =>
reader.TokenType == JsonTokenType.Null
? default
: reader.GetDateTimeOffset();
public override void Write(
Utf8JsonWriter writer,
DateTimeOffset dateTimeValue,
JsonSerializerOptions options) =>
writer.WriteStringValue(dateTimeValue);
}
}
Daftarkan pengonversi kustom ini dengan menggunakan atribut pada properti individual atau dengan menambahkan pengonversi ke Converters koleksi.
Catatan: Pengonversi sebelumnya menangani nilai null secara berbeda dari Newtonsoft.Json
yang dilakukan untuk POCO yang menentukan nilai default. Misalnya, kode berikut mewakili objek target Anda:
public class WeatherForecastWithDefault
{
public WeatherForecastWithDefault()
{
Date = DateTimeOffset.Parse("2001-01-01");
Summary = "No summary";
}
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string Summary { get; set; }
}
Dan misalkan JSON berikut dideserialisasi dengan menggunakan pengonversi sebelumnya:
{
"Date": null,
"TemperatureCelsius": 25,
"Summary": null
}
Setelah deserialisasi, properti Date
memiliki 1/1/0001 (default(DateTimeOffset)
), yaitu, nilai yang ditetapkan dalam konstruktor tertimpa. Dengan POCO dan JSON yang sama, Newtonsoft.Json
deserialisasi akan meninggalkan 1/1/2001 pada Date
properti.
Deserialisasi ke kelas dan struktur yang tidak dapat diubah
Newtonsoft.Json
dapat mendeserialisasi ke kelas dan struktur yang tidak dapat diubah karena dapat menggunakan konstruktor yang memiliki parameter.
Pada System.Text.Json, gunakan atribut [JsonConstructor] untuk menentukan penggunaan konstruktor berparameter. Rekaman di C# 9 juga tidak dapat diubah dan didukung sebagai target deserialisasi. Untuk informasi selengkapnya, lihat Jenis dan Rekaman yang Tidak Dapat Diubah.
Properti yang diperlukan
Dalam Newtonsoft.Json
, Anda menentukan agar suatu properti diperlukan dengan mengatur Required
pada [JsonProperty]
atribut. Newtonsoft.Json
memberikan pengecualian jika tidak ada nilai yang diterima di JSON untuk properti yang ditandai sebagaimana diperlukan.
Mulai dari .NET 7, Anda dapat menggunakan pengubah C# required
atau JsonRequiredAttribute atribut pada properti yang diperlukan. System.Text.Json memberikan pengecualian jika payload JSON tidak berisi nilai untuk properti yang ditandai. Untuk informasi selengkapnya, lihat Properti yang diperlukan.
System.Text.Json tidak memberikan pengecualian jika tidak ada nilai yang diterima untuk salah satu properti dari jenis target. Misalnya, jika Anda memiliki WeatherForecast
kelas:
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
JSON berikut dideserialisasi tanpa kesalahan:
{
"TemperatureCelsius": 25,
"Summary": "Hot"
}
Untuk membuat deserialisasi gagal jika tidak ada Date
properti di JSON, pilih salah satu opsi berikut:
- Gunakan .NET 7 atau versi yang lebih baru dari System.Text.Json paket dan tambahkan
required
pengubah (tersedia mulai dari C# 11) atau JsonRequiredAttribute atribut ke properti . - Menerapkan pengonversi kustom.
- Menerapkan
OnDeserialized
panggilan balik (.NET 6 dan yang lebih baru).
Contoh kode pengonversi berikut memberikan pengecualian jika Date
properti tidak diatur setelah deserialisasi selesai:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SystemTextJsonSamples
{
public class WeatherForecastRequiredPropertyConverter : JsonConverter<WeatherForecast>
{
public override WeatherForecast Read(
ref Utf8JsonReader reader,
Type type,
JsonSerializerOptions options)
{
// Don't pass in options when recursively calling Deserialize.
WeatherForecast forecast = JsonSerializer.Deserialize<WeatherForecast>(ref reader)!;
// Check for required fields set by values in JSON
return forecast!.Date == default
? throw new JsonException("Required property not received in the JSON")
: forecast;
}
public override void Write(
Utf8JsonWriter writer,
WeatherForecast forecast, JsonSerializerOptions options)
{
// Don't pass in options when recursively calling Serialize.
JsonSerializer.Serialize(writer, forecast);
}
}
}
Daftarkan pengonversi kustom ini dengan menambahkan pengonversi ke JsonSerializerOptions.Converters koleksi.
Pola pemanggilan pengonversi secara rekursif ini mengharuskan Anda mendaftarkan pengonversi dengan menggunakan JsonSerializerOptions, bukan dengan menggunakan atribut. Jika Anda mendaftarkan pengonversi dengan menggunakan atribut, pengonversi kustom akan memanggil secara rekursif. Hasilnya adalah perulangan tak terbatas yang berakhir dengan pengecualian stack overflow.
Saat Anda mendaftarkan pengonversi dengan menggunakan objek opsi, hindari perulangan tak terbatas dengan tidak meneruskan objek opsi saat memanggil Serialize atau Deserializesecara rekursif. Objek opsi berisi Converters koleksi. Jika Anda meneruskannya ke Serialize
atau Deserialize
, pengonversi kustom memanggil dirinya sendiri, membuat perulangan tak terbatas yang menghasilkan pengecualian stack overflow. Jika opsi default tidak layak, buat instans baru dari opsi dengan pengaturan yang Anda butuhkan. Pendekatan ini akan berjalan lambat karena setiap instans baru menjadi cache secara independen.
Ada pola alternatif yang dapat menggunakan JsonConverterAttribute
pendaftaran pada kelas yang akan dikonversi. Dalam pendekatan ini, kode pengonversi memanggil Serialize
atau Deserialize
pada kelas yang berasal dari kelas yang akan dikonversi. Kelas turunan tidak menerapkan JsonConverterAttribute
padanya. Dalam contoh berikut dari alternatif ini:
WeatherForecastWithRequiredPropertyConverterAttribute
adalah kelas yang akan dideserialisasi dan telah menerapkanJsonConverterAttribute
padanya.WeatherForecastWithoutRequiredPropertyConverterAttribute
adalah kelas turunan yang tidak memiliki atribut pengonversi.- Kode dalam panggilan
Serialize
konverter danDeserialize
aktifWeatherForecastWithoutRequiredPropertyConverterAttribute
untuk menghindari perulangan tak terbatas. Terdapat biaya performa untuk pendekatan ini pada serialisasi karena instansiasi objek tambahan dan penyalinan nilai properti.
Berikut adalah jenis WeatherForecast*
:
[JsonConverter(typeof(WeatherForecastRequiredPropertyConverterForAttributeRegistration))]
public class WeatherForecastWithRequiredPropertyConverterAttribute
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
public class WeatherForecastWithoutRequiredPropertyConverterAttribute :
WeatherForecastWithRequiredPropertyConverterAttribute
{
}
Dan inilah pengonversinya:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SystemTextJsonSamples
{
public class WeatherForecastRequiredPropertyConverterForAttributeRegistration :
JsonConverter<WeatherForecastWithRequiredPropertyConverterAttribute>
{
public override WeatherForecastWithRequiredPropertyConverterAttribute Read(
ref Utf8JsonReader reader,
Type type,
JsonSerializerOptions options)
{
// OK to pass in options when recursively calling Deserialize.
WeatherForecastWithRequiredPropertyConverterAttribute forecast =
JsonSerializer.Deserialize<WeatherForecastWithoutRequiredPropertyConverterAttribute>(
ref reader,
options)!;
// Check for required fields set by values in JSON.
return forecast!.Date == default
? throw new JsonException("Required property not received in the JSON")
: forecast;
}
public override void Write(
Utf8JsonWriter writer,
WeatherForecastWithRequiredPropertyConverterAttribute forecast,
JsonSerializerOptions options)
{
var weatherForecastWithoutConverterAttributeOnClass =
new WeatherForecastWithoutRequiredPropertyConverterAttribute
{
Date = forecast.Date,
TemperatureCelsius = forecast.TemperatureCelsius,
Summary = forecast.Summary
};
// OK to pass in options when recursively calling Serialize.
JsonSerializer.Serialize(
writer,
weatherForecastWithoutConverterAttributeOnClass,
options);
}
}
}
Pengonversi properti yang diperlukan akan memerlukan logika tambahan jika Anda perlu menangani atribut seperti [JsonIgnore] atau opsi yang berbeda, seperti encoder kustom. Selain itu, kode contoh tidak menangani properti yang nilai defaultnya diatur dalam konstruktor. Dan pendekatan ini tidak membedakan antara skenario berikut:
- Properti hilang dari JSON.
- Properti untuk jenis yang tidak dapat diubah ke null ada pada JSON, tetapi nilainya adalah default untuk jenis tersebut, seperti nol untuk
int
. - Properti untuk jenis nilai yang dapat diubah ke null ada di JSON, tetapi nilainya null.
Catatan
Jika Anda menggunakan System.Text.Json dari pengontrol ASP.NET Core, Anda mungkin dapat menggunakan [Required]
atribut pada properti kelas model alih-alih menerapkan System.Text.Json pengonversi.
Tentukan format tanggal
Newtonsoft.Json
menyediakan beberapa cara untuk mengontrol bagaimana properti jenis DateTime
dan DateTimeOffset
diserialisasikan dan dideserialisasi:
DateTimeZoneHandling
Pengaturan dapat digunakan untuk menserialisasikan semuaDateTime
nilai sebagai tanggal UTC.DateFormatString
Pengaturan danDateTime
pengonversi dapat digunakan untuk menyesuaikan format string tanggal.
System.Text.Json mendukung ISO 8601-1:2019, termasuk profil RFC 3339. Format ini diadopsi secara luas, tidak ambigu, dan melakukan perjalanan pulang pergi dengan tepat. Untuk menggunakan format lain, buat pengonversi kustom. Misalnya, pengonversi berikut menserialisasikan dan mendeserialisasi JSON yang menggunakan format epoch Unix dengan atau tanpa offset zona waktu (nilai seperti /Date(1590863400000-0700)/
atau /Date(1590863400000)/
):
sealed class UnixEpochDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
{
static readonly DateTimeOffset s_epoch = new(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
static readonly Regex s_regex = new("^/Date\\(([+-]*\\d+)([+-])(\\d{2})(\\d{2})\\)/$", RegexOptions.CultureInvariant);
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string formatted = reader.GetString()!;
Match match = s_regex.Match(formatted);
if (
!match.Success
|| !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime)
|| !int.TryParse(match.Groups[3].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int hours)
|| !int.TryParse(match.Groups[4].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int minutes))
{
throw new JsonException();
}
int sign = match.Groups[2].Value[0] == '+' ? 1 : -1;
TimeSpan utcOffset = new(hours * sign, minutes * sign, 0);
return s_epoch.AddMilliseconds(unixTime).ToOffset(utcOffset);
}
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
{
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
TimeSpan utcOffset = value.Offset;
string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime}{(utcOffset >= TimeSpan.Zero ? "+" : "-")}{utcOffset:hhmm})/");
writer.WriteStringValue(formatted);
}
}
sealed class UnixEpochDateTimeConverter : JsonConverter<DateTime>
{
static readonly DateTime s_epoch = new(1970, 1, 1, 0, 0, 0);
static readonly Regex s_regex = new("^/Date\\(([+-]*\\d+)\\)/$", RegexOptions.CultureInvariant);
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string formatted = reader.GetString()!;
Match match = s_regex.Match(formatted);
if (
!match.Success
|| !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime))
{
throw new JsonException();
}
return s_epoch.AddMilliseconds(unixTime);
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime})/");
writer.WriteStringValue(formatted);
}
}
Untuk informasi selengkapnya, lihat Dukungan DateTime dan DateTimeOffset di System.Text.Json.
Panggilan balik
Newtonsoft.Json
memungkinkan Anda menjalankan kode kustom di beberapa titik dalam proses serialisasi atau deserialisasi:
- OnDeserializing (ketika mulai mendeserialisasi objek)
- OnDeserialized (ketika selesai mendeserialisasi objek)
- OnSerializing (ketika mulai menserialisasikan objek)
- OnSerialized (ketika selesai menserialisasikan objek)
System.Text.Json mengekspos pemberitahuan yang sama selama serialisasi dan deserialisasi. Untuk menggunakannya, terapkan satu atau beberapa antarmuka berikut dari System.Text.Json.Serialization namespace layanan:
Berikut adalah contoh yang memeriksa properti null dan menulis pesan di awal dan akhir serialisasi dan deserialisasi:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Callbacks
{
public class WeatherForecast :
IJsonOnDeserializing, IJsonOnDeserialized,
IJsonOnSerializing, IJsonOnSerialized
{
public DateTime Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
void IJsonOnDeserializing.OnDeserializing() => Console.WriteLine("\nBegin deserializing");
void IJsonOnDeserialized.OnDeserialized()
{
Validate();
Console.WriteLine("Finished deserializing");
}
void IJsonOnSerializing.OnSerializing()
{
Console.WriteLine("Begin serializing");
Validate();
}
void IJsonOnSerialized.OnSerialized() => Console.WriteLine("Finished serializing");
private void Validate()
{
if (Summary is null)
{
Console.WriteLine("The 'Summary' property is 'null'.");
}
}
}
public class Program
{
public static void Main()
{
var weatherForecast = new WeatherForecast
{
Date = DateTime.Parse("2019-08-01"),
TemperatureCelsius = 25,
};
string jsonString = JsonSerializer.Serialize(weatherForecast);
Console.WriteLine(jsonString);
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString);
Console.WriteLine($"Date={weatherForecast?.Date}");
Console.WriteLine($"TemperatureCelsius={weatherForecast?.TemperatureCelsius}");
Console.WriteLine($"Summary={weatherForecast?.Summary}");
}
}
}
// output:
//Begin serializing
//The 'Summary' property is 'null'.
//Finished serializing
//{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":null}
//Begin deserializing
//The 'Summary' property is 'null'.
//Finished deserializing
//Date=8/1/2019 12:00:00 AM
//TemperatureCelsius = 25
//Summary=
Kode OnDeserializing
tidak memiliki akses ke instans POCO baru. Untuk memanipulasi instans POCO baru di awal deserialisasi, letakkan kode tersebut di konstruktor POCO.
Dukungan untuk setter dan getter properti non-publik
Newtonsoft.Json
dapat menggunakan setter properti privat dan internal dan getter melalui JsonProperty
atribut.
System.Text.Json mendukung setter properti privat dan internal dan getter melalui atribut [JsonInclude]. Untuk kode sampel, lihat Pengakses properti non-publik.
Mengisi objek yang ada
Metode JsonConvert.PopulateObject
dalam Newtonsoft.Json
mendeserialisasi dokumen JSON ke instans kelas yang ada, alih-alih membuat instans baru. System.Text.Json selalu membuat instans baru dari jenis target dengan menggunakan konstruktor tanpa parameter publik default. Pengonversi kustom dapat mendeserialisasi ke instans yang ada.
Gunakan kembali daripada mengganti properti
Mulai dari .NET 8, System.Text.Json mendukung penggunaan kembali properti yang diinisialisasi daripada menggantinya. Ada beberapa perbedaan perilaku, yang dapat Anda baca di proposal API.
Untuk informasi selengkapnya, lihat Mengisi properti yang diinisialisasi.
Pengaturan ObjectCreationHandling
di Newtonsoft.Json
memungkinkan Anda menentukan bahwa objek dalam properti harus digunakan kembali daripada diganti selama deserialisasi. System.Text.Json selalu mengganti objek dalam properti. Pengonversi kustom dapat menyediakan fungsionalitas ini, atau Anda dapat meningkatkan ke .NET 8, yang menyediakan fungsionalitas pengisian.
Mengisi properti tanpa setter
Mulai dari .NET 8, System.Text.Json mendukung pengisian properti, termasuk yang tidak memiliki setter. Untuk informasi selengkapnya, lihat Mengisi properti yang diinisialisasi.
Selama deserialisasi, Newtonsoft.Json
menambahkan objek ke koleksi meskipun properti tidak memiliki setter. System.Text.Json mengabaikan properti yang tidak memiliki setter. Pengonversi kustom dapat menyediakan fungsionalitas ini, atau Anda dapat meningkatkan ke .NET 8, yang dapat mengisi properti baca-saja.
Kebijakan penamaan snake case
System.Text.Json termasuk kebijakan penamaan bawaan untuk kasus ular. Namun, ada beberapa perbedaan perilaku dengan Newtonsoft.Json
untuk beberapa input. Tabel berikut menunjukkan beberapa perbedaan ini saat mengonversi input menggunakan JsonNamingPolicy.SnakeCaseLower kebijakan.
Input | Newtonsoft.Json hasil | System.Text.Json hasil |
---|---|---|
"AB1" | "a_b1" | "ab1" |
"SHA512Managed" | "sh_a512_managed" | "sha512_managed" |
"abc123DEF456" | "abc123_de_f456" | "abc123_def456" |
"KEBAB-CASE" | "keba_b-_case" | "kebab-case" |
Satu-satunya kebijakan penamaan properti bawaan adalah System.Text.Json untuk kasus camel. Newtonsoft.Json
dapat mengonversi nama properti menjadi snake case. Kebijakan penamaan kustom dapat menyediakan fungsionalitas ini, atau meningkatkan ke .NET 8 atau yang lebih baru, yang mencakup kebijakan penamaan kasus ular bawaan.
Atribut System.Runtime.Serialization
System.Runtime.Serializationatribut seperti DataContractAttribute, , dan IgnoreDataMemberAttribute memungkinkan Anda menentukan kontrak data. DataMemberAttribute Kontrak data adalah perjanjian formal antara layanan dan klien yang secara abstrak menjelaskan data yang akan ditukar. Kontrak data secara tepat menentukan properti mana yang diserialisasikan untuk pertukaran.
System.Text.Json tidak memiliki dukungan bawaan untuk atribut ini. Namun, mulai dari .NET 7, Anda dapat menggunakan pemecah masalah jenis kustom untuk menambahkan dukungan. Untuk sampel, lihat ZCS. DataContractResolver.
Angka oktal
Newtonsoft.Json
memperlakukan angka dengan nol di depannya sebagai angka oktal. System.Text.Json tidak mengizinkan nol di depan karena spesifikasi RFC 8259 tidak mengizinkannya.
Menangani anggota yang hilang
Jika JSON yang sedang dideserialisasi menyertakan properti yang hilang dalam jenis target, Newtonsoft.Json
dapat dikonfigurasi untuk melemparkan pengecualian. Secara default, System.Text.Json mengabaikan properti tambahan di JSON, kecuali saat Anda menggunakan atribut [JsonExtensionData].
Di .NET 8 dan versi yang lebih baru, Anda dapat mengatur preferensi Anda apakah akan melewati atau melarang properti JSON yang tidak dipetakan menggunakan salah satu cara berikut:
- Terapkan JsonUnmappedMemberHandlingAttribute atribut ke jenis yang Anda deserialisasi.
- Untuk mengatur preferensi Anda secara global, atur JsonSerializerOptions.UnmappedMemberHandling properti . Atau, untuk pembuatan sumber, atur JsonSourceGenerationOptionsAttribute.UnmappedMemberHandling properti dan terapkan atribut ke kelas Anda JsonSerializerContext .
- Sesuaikan JsonTypeInfo.UnmappedMemberHandling properti .
JsonObjectAttribute
Newtonsoft.Json
memiliki atribut, JsonObjectAttribute
, yang dapat diterapkan pada tingkat jenis untuk mengontrol anggota mana yang diserialisasikan, bagaimana null
nilai ditangani, dan apakah semua anggota diperlukan. System.Text.Json tidak memiliki atribut yang setara yang dapat diterapkan pada jenis. Untuk beberapa perilaku, seperti null
penanganan nilai, Anda dapat mengonfigurasi perilaku yang sama pada global JsonSerializerOptions atau satu per satu pada setiap properti.
Pertimbangkan contoh berikut yang menggunakan Newtonsoft.Json.JsonObjectAttribute
untuk menentukan bahwa semua null
properti harus diabaikan:
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class Person { ... }
Di System.Text.Json, Anda dapat mengatur perilaku untuk semua jenis dan properti:
JsonSerializerOptions options = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
string json = JsonSerializer.Serialize<Person>(person, options);
Atau Anda dapat mengatur perilaku pada setiap properti secara terpisah:
public class Person
{
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Name { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? Age { get; set; }
}
Selanjutnya, pertimbangkan contoh berikut yang menggunakan Newtonsoft.Json.JsonObjectAttribute
untuk menentukan bahwa semua properti anggota harus ada di JSON:
[JsonObject(ItemRequired = Required.Always)]
public class Person { ... }
Anda dapat mencapai perilaku yang sama dengan System.Text.Json menambahkan pengubah C# required
atau ke JsonRequiredAttribute setiap properti. Untuk informasi selengkapnya, lihat Properti yang diperlukan.
public class Person
{
[JsonRequired]
public string? Name { get; set; }
public required int? Age { get; set; }
}
TraceWriter
Newtonsoft.Json
memungkinkan Anda men-debug dengan menggunakan TraceWriter
untuk melihat log yang dihasilkan oleh serialisasi atau deserialisasi. System.Text.Json tidak melakukan pengelogan.
JsonDocument dan JsonElement dibandingkan dengan JToken (seperti JObject, JArray)
System.Text.Json.JsonDocument menyediakan kemampuan untuk mengurai dan membangun Model Objek Dokumen (DOM) baca-saja dari payload JSON yang ada. DOM menyediakan akses acak ke data dalam payload JSON. Elemen JSON yang menyusun payload dapat diakses melalui jenis JsonElement. Jenis JsonElement
ini menyediakan API untuk mengonversi teks JSON ke jenis .NET umum. JsonDocument
mengekspos RootElement properti.
Mulai dari .NET 6, Anda dapat mengurai dan membangun DOM yang dapat diubah dari payload JSON yang ada dengan menggunakan JsonNode jenis dan jenis lain di System.Text.Json.Nodes namespace layanan. Untuk informasi lebih lanjut, lihat Penggunaan JsonNode
.
JsonDocument adalah IDisposable
JsonDocument
membuat tampilan data dalam memori ke dalam buffer yang dikumpulkan. Oleh karena itu, tidak seperti JObject
atau JArray
dari Newtonsoft.Json
, jenis JsonDocument
mengimplementasikan IDisposable
dan perlu digunakan di dalam blok penggunaan. Untuk informasi selengkapnya, lihat JsonDocument adalah IDisposable.
JsonDocument bersifat baca-saja
System.Text.Json DOM tidak dapat menambahkan, menghapus, atau memodifikasi elemen JSON. Dirancang seperti ini untuk performa dan untuk mengurangi alokasi demi menguraikan ukuran payload JSON umum (yaitu, < 1 MB).
JsonElement adalah struktur perpaduan
JsonDocument
mengekspos RootElement
sebagai properti jenis JsonElement, yang merupakan jenis struktur gabungan yang mencakup elemen JSON apa pun. Newtonsoft.Json
menggunakan jenis hierarki khusus seperti JObject
, , JArray
JToken
, dan sebagainya. JsonElement
adalah apa yang dapat Anda cari dan hitung, dan Anda dapat menggunakan JsonElement
untuk mewujudkan elemen JSON ke dalam jenis .NET.
Mulai dari .NET 6, Anda dapat menggunakan JsonNode jenis dan jenis di System.Text.Json.Nodes namespace yang sesuai dengan JObject
, , JArray
dan JToken
. Untuk informasi lebih lanjut, lihat Penggunaan JsonNode
.
Cara mencari JsonDocument dan JsonElement untuk subelemen
Pencarian token JSON menggunakan JObject
atau JArray
dari Newtonsoft.Json
cenderung relatif cepat karena mereka mencari dari beberapa kamus. Sebagai perbandingan, pencarian pada JsonElement
memerlukan pencarian properti secara berurutan dan membuatnya menjadi relatif lambat (misalnya saat menggunakan TryGetProperty
). System.Text.Json dirancang untuk meminimalkan waktu penguraian awal daripada waktu pencarian. Untuk informasi tentang DOM, lihat Cara mencari JsonDocument dan JsonElement untuk sub-elemen.
Utf8JsonReader vs. JsonTextReader
System.Text.Json.Utf8JsonReaderadalah pembaca berkinerja tinggi, beralokasi rendah, pembaca terusan untuk teks JSON yang dikodekan oleh UTF-8, baca dari ReadOnlySpan<byte> atau ReadOnlySequence<byte>. Utf8JsonReader
adalah jenis tingkat rendah yang dapat digunakan untuk membuat pengurai dan deserializer khusus.
Utf8JsonReader adalah struktur ref
JsonTextReader
padai Newtonsoft.Json
adalah sebuah kelas. Jenis Utf8JsonReader
berbeda karena ini adalah struktur ref. Untuk informasi selengkapnya, lihat batasan struktur ref untuk Utf8JsonReader.
Membaca nilai null ke dalam jenis nilai nullable
Newtonsoft.Json
menyediakan API yang mengembalikan , seperti ReadAsBoolean
, yang menangani Null
TokenType
untuk Anda dengan mengembalikan bool?
.Nullable<T> API System.Text.Json
bawaan hanya mengembalikan jenis nilai yang tidak dapat diubah ke null. Untuk informasi selengkapnya, lihat Membaca nilai null ke dalam jenis nilai null.
Multi-target untuk membaca JSON
Jika Anda perlu terus menggunakan Newtonsoft.Json
untuk kerangka kerja target tertentu, Anda dapat melakukan multi-target dan memiliki dua implementasi. Namun, ini tidak sepele dan akan membutuhkan beberapa #ifdefs
dan duplikasi sumber. Salah satu cara untuk berbagi kode sebanyak mungkin adalah dengan membuat ref struct
pembungkus di sekitar Utf8JsonReader dan Newtonsoft.Json.JsonTextReader
. Pembungkus ini akan menyatukan area permukaan publik sambil mengisolasi perbedaan perilaku. Ini memungkinkan Anda mengisolasi perubahan terutama pada konstruksi jenis, bersamaan dengan melewati jenis baru berdasarkan referensi. Ini adalah pola yang diikuti oleh pustaka Microsoft.Extensions.DependencyModel:
Utf8JsonWriter vs. JsonTextWriter
System.Text.Json.Utf8JsonWriter adalah cara beperforma tinggi untuk menulis teks JSON yang dikodekan UTF-8 dari jenis .NET umum seperti String
, Int32
, dan DateTime
. Penulis adalah jenis tingkat rendah yang dapat digunakan untuk membangun serializer kustom.
Menulis nilai mentah
Newtonsoft.Json
memiliki WriteRawValue
metode yang menulis JSON mentah di mana nilai diharapkan. System.Text.Json memiliki persamaan langsung: Utf8JsonWriter.WriteRawValue. Untuk informasi selengkapnya, lihat Menulis JSON mentah.
Mengkustomisasi format JSON
JsonTextWriter
termasuk pengaturan berikut, di mana Utf8JsonWriter tidak memiliki persamaan:
- QuoteChar - Menentukan karakter yang akan digunakan untuk mengelilingi nilai string.
Utf8JsonWriter
selalu menggunakan tanda kutip ganda. - QuoteName - Menentukan apakah akan mengelilingi nama properti dengan tanda kutip atau tidak.
Utf8JsonWriter
selalu mengelilinginya dengan tanda kutip.
Mulai dari .NET 9, Anda dapat menyesuaikan karakter dan ukuran indentasi untuk Utf8JsonWriter menggunakan opsi yang JsonWriterOptions diekspos oleh struktur:
JsonTextWriter
termasuk pengaturan berikut, di mana Utf8JsonWriter
tidak memiliki persamaan:
- Indentasi - Menentukan berapa banyak karakter yang akan diindentasi.
Utf8JsonWriter
selalu inden sebesar 2 karakter. - IndentChar - Menentukan karakter yang akan digunakan untuk indentasi.
Utf8JsonWriter
selalu menggunakan spasi kosong. - QuoteChar - Menentukan karakter yang akan digunakan untuk mengelilingi nilai string.
Utf8JsonWriter
selalu menggunakan tanda kutip ganda. - QuoteName - Menentukan apakah akan mengelilingi nama properti dengan tanda kutip atau tidak.
Utf8JsonWriter
selalu mengelilinginya dengan tanda kutip.
Tidak ada solusi yang memungkinkan Anda menyesuaikan JSON yang dihasilkan Utf8JsonWriter
dengan cara ini.
Menulis nilai Rentang Waktu, Uri, atau nilai char
JsonTextWriter
menyediakan WriteValue
metode untuk TimeSpan, Uri, dan nilai karakter. Utf8JsonWriter
tidak memiliki metode yang setara. Sebagai gantinya, formatlah nilai-nilai ini sebagai string (dengan memanggil ToString()
, misalnya) dan panggil WriteStringValue.
Multi-target untuk menulis JSON
Jika Anda perlu terus menggunakan Newtonsoft.Json
untuk kerangka kerja target tertentu, Anda dapat melakukan multi-target dan memiliki dua implementasi. Namun, ini tidak sepele dan akan membutuhkan beberapa #ifdefs
dan duplikasi sumber. Salah satu cara untuk berbagi kode sebanyak mungkin adalah dengan membuat pembungkus di sekitar Utf8JsonWriterdan Newtonsoft.Json.JsonTextWriter
. Pembungkus ini akan menyatukan area permukaan publik sambil mengisolasi perbedaan perilaku. Ini memungkinkan Anda mengisolasi perubahan terutama pada konstruksi jenis. Pustaka Microsoft.Extensions.DependencyModel mengikuti:
TypeNameHandling.All tidak didukung
Keputusan untuk mengecualikan fungsionalitas setara TypeNameHandling.All
dari System.Text.Json
dilakukan dengan sengaja. Mengizinkan payload JSON untuk menentukan informasi jenisnya sendiri adalah sumber kerentanan umum dalam aplikasi web. Secara khusus, mengonfigurasi Newtonsoft.Json
dengan TypeNameHandling.All
memungkinkan klien jarak jauh untuk menyematkan seluruh aplikasi yang dapat dieksekusi dalam payload JSON itu sendiri, sehingga selama deserialisasi, aplikasi web mengekstrak dan menjalankan kode yang disematkan. Untuk informasi selengkapnya, lihat PowerPoint serangan JSON pada Jumat tanggal 13 dan detail serangan JSON pada Jumat tanggal 13.
Kueri Jalur JSON tidak didukung
DOM JsonDocument
tidak mendukung kueri dengan menggunakan JSON Path.
Pada DOM JsonNode, setiap JsonNode
instans memiliki GetPath
metode yang mengembalikan jalur ke simpul tersebut. Tetapi tidak ada API bawaan untuk menangani kueri berdasarkan string kueri JSON Path.
Untuk informasi selengkapnya, lihat masalah GitHub dotnet/runtime #31068.
Beberapa batasan tidak dapat dikonfigurasi
System.Text.Json menetapkan batas yang tidak dapat diubah untuk beberapa nilai, seperti ukuran token maksimum dalam karakter (166 MB) dan dalam basis 64 (125 MB). Untuk informasi selengkapnya, lihat JsonConstants
pada kode sumber dan masalah GitHub dotnet/runtime #39953.
Nan, Infinity, -Infinity
Newtonsoft mengurai token string JSON NaN
, Infinity
, dan -Infinity
. Dengan System.Text.Json, gunakan JsonNumberHandling.AllowNamedFloatingPointLiterals. Untuk informasi tentang cara menggunakan pengaturan ini, lihat Mengizinkan atau menulis angka dalam tanda kutip.
Menggunakan GitHub Copilot untuk bermigrasi
Anda bisa mendapatkan bantuan pengkodean dari GitHub Copilot untuk mengonversi kode Anda dalam IDE Anda.
Jika Anda menggunakan Visual Studio 2022 versi 17.8 atau yang lebih baru, Anda dapat mencoba GitHub Copilot berbasis AI di Visual Studio untuk membantu memigrasikan kode Anda Newtonsoft.Json
untuk menggunakan System.Text.Json
. Kirimkan pertanyaan Anda dan kode untuk dikonversi sebagai perintah di jendela obrolan salinan, seperti dalam contoh berikut.
Catatan
GitHub Copilot didukung oleh AI, sehingga kejutan dan kesalahan dimungkinkan. Pastikan untuk memverifikasi kode atau saran yang dihasilkan. Untuk informasi selengkapnya tentang penggunaan umum GitHub Copilot, dampak produk, pengawasan manusia, dan privasi, lihat Tanya Jawab Umum GitHub Copilot.
Contoh perintah untuk Obrolan Salinan
convert the following code to use System.Text.Json
Product product = new Product();
product.Name = "Apple";
product.ExpiryDate = new DateTime(2024, 08, 08);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string output = JsonConvert.SerializeObject(product);
Console.WriteLine(output);
Contoh respons Obrolan Salinan
To convert the code to use System.Text.Json, you can use the JsonSerializer class. Here's the updated code:
using System;
using System.Text.Json;
public class Product
{
public string Name { get; set; }
public DateTime ExpiryDate { get; set; }
public decimal Price { get; set; }
public string[] Sizes { get; set; }
}
public class Program
{
public static void Main()
{
Product product = new Product();
product.Name = "Apple";
product.ExpiryDate = new DateTime(2024, 08, 08);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string output = JsonSerializer.Serialize(product);
Console.WriteLine(output);
}
}
This code uses System.Text.Json.JsonSerializer.Serialize to convert the Product object to a JSON string.
Perhatikan bahwa hasil Anda mungkin berbeda dari apa yang ditunjukkan dalam contoh respons ini. Model AI tidak deterministik, yang berarti bahwa mereka dapat mengembalikan respons yang berbeda ketika diajukan pertanyaan yang sama. Ini mungkin karena pembelajaran dan adaptasi tambahan dari waktu ke waktu, variasi bahasa, perubahan konteks, seperti riwayat obrolan Anda, dan banyak lagi.
Anda dapat menggunakan fitur obrolan, seperti perintah garis miring, referensi, dan utas, untuk mengatur niat dan mendapatkan jawaban yang lebih baik dengan konteks tercakup.
Misalnya, jika file filename
kode Anda terbuka di IDE, Anda dapat mereferensikan file dalam permintaan Anda ke Obrolan Copilot dengan "konversi #filename
untuk menggunakan System.Text.Json
". Atau Anda dapat mereferensikan solusi dengan "konversi @workspace
untuk digunakan System.Text.Json
" di jendela obrolan atau dalam obrolan sebaris.