Kami memiliki beberapa file konfigurasi yang dihasilkan dengan membuat serialisasi objek C # dengan Json.net.
Kami ingin memindahkan satu properti kelas berseri dari properti enum sederhana menjadi properti kelas.
Salah satu cara mudah untuk melakukan ini, akan meninggalkan properti enum lama di kelas, dan mengatur agar Json.net membaca properti ini saat kita memuat konfigurasi, tetapi tidak menyimpannya lagi saat kita menyusun objek berikutnya. Kami akan berurusan dengan menghasilkan kelas baru dari enum lama secara terpisah.
Apakah ada cara sederhana untuk menandai (misalnya dengan atribut) properti dari objek C #, sehingga Json.net akan mengabaikannya HANYA saat membuat serial, tetapi mengatasinya saat melakukan deserialisasi?
Jawaban:
Sebenarnya ada beberapa pendekatan yang cukup sederhana yang dapat Anda gunakan untuk mencapai hasil yang Anda inginkan.
Mari kita asumsikan, misalnya, bahwa kelas Anda saat ini ditentukan seperti ini:
Dan Anda ingin melakukan ini:
Untuk mendapatkan ini:
Pendekatan 1: Tambahkan metode ShouldSerialize
Json.NET memiliki kemampuan untuk membuat serialisasi properti secara bersyarat dengan mencari
ShouldSerialize
metode yang sesuai di kelas.Untuk menggunakan fitur ini, tambahkan
ShouldSerializeBlah()
metode boolean ke kelas Anda yangBlah
akan diganti dengan nama properti yang tidak ingin Anda buat serialnya. Jadikan penerapan metode ini selalu kembalifalse
.Catatan: jika Anda menyukai pendekatan ini tetapi tidak ingin merusak antarmuka publik kelas Anda dengan memperkenalkan
ShouldSerialize
metode, Anda dapat menggunakanIContractResolver
untuk melakukan hal yang sama secara terprogram. Lihat Serialisasi Properti Bersyarat dalam dokumentasi.Pendekatan 2: Memanipulasi JSON dengan JObjects
Alih-alih menggunakan
JsonConvert.SerializeObject
untuk melakukan serialisasi, muat objek config ke aJObject
, lalu hapus properti yang tidak diinginkan dari JSON sebelum menulisnya. Itu hanya beberapa baris kode tambahan.Pendekatan 3: Penggunaan atribut yang cerdik (ab)
[JsonIgnore]
atribut ke properti yang Anda tidak ingin menjadi serial.[JsonProperty]
atribut ke penyetel alternatif, memberinya nama JSON yang sama dengan properti aslinya.Inilah
Config
kelas yang direvisi :sumber
JsonPropertyAttribute
, dari C # 6.0 Anda dapat menggunakannameof
kata kunci daripada menggunakan "string ajaib". Hal ini membuat pemfaktoran ulang menjadi jauh lebih mudah dan sangat mudah - plus, jika Anda melewatkan mengganti nama kejadian apa pun, kompilator akan memperingatkan Anda. Menggunakan contoh @ Brian, penggunaannya akan seperti ini:[JsonProperty(nameof(ObsoleteSetting))]
Untuk situasi apa pun yang mengizinkan properti khusus deserialisasi Anda ditandai internal, ada solusi yang sangat sederhana yang tidak bergantung pada atribut sama sekali. Cukup tandai properti sebagai get internal, tetapi set publik:
Ini menghasilkan deserialisasi yang benar menggunakan pengaturan default / resolver / dll., Tetapi properti dihapus dari output serial.
sumber
get
metode publik ).internal
norprivate
. Itu selalu berseri.Saya suka menempel dengan atribut yang satu ini, berikut adalah metode yang saya gunakan ketika perlu deserialisasi properti tetapi tidak membuat serial atau sebaliknya.
LANGKAH 1 - Buat atribut khusus
LANGKAH 2 - Buat Pengembalian Kontrak kustom
LANGKAH 3 - Tambahkan atribut di mana serialisasi tidak diperlukan tetapi deserialisasi diperlukan
LANGKAH 4 - Gunakan
Semoga ini membantu! Juga perlu dicatat bahwa ini juga akan mengabaikan properti ketika Deserialization terjadi, ketika saya melakukan derserialisasi, saya hanya menggunakan konverter dengan cara konvensional.
sumber
GetSerializableMembers
daripada menimpanya seluruhnya?return base.GetSerializableMembers(objectType).Where(pi => !Attribute.IsDefined(pi, typeof(JsonIgnoreSerializationAttribute))).ToList();
JsonConvert.DefaultSettings = () => new JsonSerializerSettings { ContractResolver = new JsonPropertiesResolver() }
Gunakan properti setter:
Semoga bantuan ini.
sumber
IgnoreOnSerializing
, sama dengan properti. Saya merekomendasikan penggunaannameof(IgnoreOnSerializing)
untuk menghindari string ajaib, dalam kasus penggantian nama.Setelah saya menghabiskan waktu yang cukup lama mencari bagaimana menandai properti kelas menjadi De-Serializable dan NOT Serializable saya menemukan bahwa tidak ada hal seperti itu untuk melakukan itu sama sekali; jadi saya datang dengan solusi yang menggabungkan dua pustaka yang berbeda atau teknik serialisasi (System.Runtime.Serialization.Json & Newtonsoft.Json) dan itu bekerja untuk saya seperti berikut:
kemudian lakukan serialisasi menggunakan "Newtonsoft.Json.JsonConvert.SerializeObject" dan De-Serialize menggunakan "System.Runtime.Serialization.Json.DataContractJsonSerializer".
Semoga membantu ...
sumber
dengan mengacu pada solusi @ ThoHo, penggunaan setter sebenarnya adalah semua yang diperlukan, tanpa tag tambahan.
Bagi saya, saya sebelumnya memiliki satu ID referensi, yang ingin saya muat dan tambahkan ke koleksi ID referensi baru. Dengan mengubah definisi Id referensi agar hanya berisi metode penyetel, yang menambahkan nilai ke koleksi baru. Json tidak dapat menulis kembali nilainya jika Properti tidak memiliki get; metode.
Kelas ini sekarang kompatibel dengan versi sebelumnya dan hanya menyimpan Referensi untuk versi baru.
sumber
Untuk mengembangkan jawaban Tho Ho, ini juga dapat digunakan untuk ladang.
sumber
Bergantung di mana dalam aplikasi ini terjadi dan jika itu hanya satu properti, satu cara manual yang dapat Anda lakukan adalah dengan menyetel nilai properti ke null dan kemudian pada model Anda dapat menentukan bahwa properti diabaikan jika nilainya null:
Jika Anda bekerja pada aplikasi web ASP.NET Core, Anda dapat mengatur ini secara global untuk semua properti di semua model dengan mengatur ini di file Startup.cs Anda:
sumber
Jika Anda menggunakan JsonConvert, IgnoreDataMemberAttribute is ok. Pustaka standar saya tidak refence Newton.Json, dan saya menggunakan [IgnoreDataMember] untuk mengontrol serialisasi objek.
Dari dokumen bantuan Newton.net .
sumber
Cara termudah yang saya temukan pada tulisan ini adalah dengan memasukkan logika ini ke dalam IContractResolver Anda .
Kode contoh dari tautan di atas disalin di sini untuk anak cucu:
Semua jawaban bagus tetapi pendekatan ini sepertinya cara yang paling bersih. Saya benar-benar menerapkan ini dengan mencari atribut pada properti untuk SkipSerialize dan SkipDeserialize sehingga Anda dapat menandai kelas apa pun yang Anda kontrol. Pertanyaan bagus!
sumber