Halo, Habr! Saya ingin berbagi dengan Anda perpustakaan saya untuk deserializing objek JSON ke dalam kelas, yang juga secara otomatis memvalidasi data input berdasarkan tipe.
Belum lama ini, hal yang luar biasa seperti kelas muncul dalam JavaScript, yang sangat menyederhanakan proses penulisan kode. Namun sayangnya fungsionalitas untuk deserializing JSON ke dalam kelas yang sama ini tidak muncul, mis. Anda dapat membuat cerita bersambung suatu kelas menjadi sebuah string, tetapi kembali sendiri. Dan untuk memperbaiki kelemahan ini, pustaka
ts-serializable ditulis yang ingin saya bagikan dengan Anda.
Esensi masalah ditunjukkan oleh kode berikut:
export class User { public firstName: string = ""; public lastName: string = ""; public birthDate: Date = new Date(); public getFullName(): string { return [this.firstName, this.lastName].join(' '); } public getAge(): number { return new Date().getFullYear() - this.birthDate.getFullYear(); } } const ivan = new User(); ivan.getFullName();
Apa penyebab kesalahan Ivan yang baru? Faktanya adalah bahwa metode JSON.parse tidak deserialize ke kelas Pengguna, tetapi ke kelas Objek, yang sama sekali tidak memiliki metode getFullName dan getAge.
Bagaimana perpustakaan saya membantu menyelesaikan masalah ini dan menghapusnya dalam User daripada Object? Cukup dengan sedikit memodifikasi kode:
import { jsonProperty, Serializable } from "ts-serializable"; export class User extends Serializable { @jsonProperty(String) public firstName: string = ""; @jsonProperty(String) public lastName: string = ""; @jsonProperty(Date) public birthDate: Date = new Date(); public getFullName(): string { return [this.firstName, this.lastName].join(' '); } public getAge(): number { return new Date().getFullYear() - this.birthDate.getFullYear(); } } const ivan = new User(); ivan.getFullName(); // ivan.getAge(); // ivan instanceof User; // const text = JSON.stringify(ivan); // const newIvan = new User().fromJson(JSON.parse(text)); // User newIvan.getFullName(); // newIvan.getAge(); // newIvan instanceof User; //
Semuanya sangat sederhana. Kami mewarisi kelas kami dari kelas Serializable, yang memiliki dua metode fromJson untuk deserialisasi dan toJSON untuk serialisasi, dan kami menggantung dekorator @jsonProperty dengan properti yang diizinkan untuk diterima dari JSON. Data yang tidak valid akan diabaikan, peringatan akan dikeluarkan ke konsol, dan nilai default akan tetap di properti.
Pada dasarnya itu. Sekarang di bagian depan, Anda dapat menghapus dan serialisasi semudah yang Anda lakukan dalam C #, Java, dan bahasa lainnya. Berdasarkan perilaku Newtonsoft Json.NET.
Faq
Mengapa mewarisi dari Serializable?Untuk menambahkan dua metode fromJson dan toJSON ke model. Anda dapat melakukan hal yang sama melalui dekorator atau kera. Tetapi pewarisan adalah metode yang lebih tepat untuk naskah.
Bagaimana validasi data terjadiDi dekorator, Anda harus menetapkan konstruktor tipe data yang diizinkan untuk diterima dari JSON. Boolean, String, Number objek akan mengembalikan boolean, string, number, masing-masing. Jika Anda perlu menerima array, maka jenisnya dibingkai oleh tanda kurung array, misalnya @jsonProperty ([String]). Jika konstruktor diwarisi dari kelas Serializable, maka itu juga akan deserialized ke dalam kelas, jika tidak, objek akan dikembalikan.
Bagaimana cara menangkap kesalahan validasi?Secara default, perpustakaan hanya menulis peringatan ke konsol tentang kesalahan validasi. Untuk mengganti perilaku ini, seperti melempar pengecualian atau masuk ke backend, Anda harus mengganti metode onWrongType model.
Bonus 1. Salinan dalam.
const user1 = new Uesr(); const user2 = new User().fromJson(user1);
Bonus 2. Malas ViewModels.
Jika Anda perlu membuat model dengan data tambahan, misalnya untuk tampilan, tetapi yang tidak diterima oleh backend, Anda dapat dengan mudah memperluas model dengan properti baru dan menandai properti ini dengan dekorator @jsonIgnore. Dan kemudian properti ini tidak akan diserialisasi.
import { jsonProperty, Serializable } from "ts-serializable"; export class User extends Serializable { @jsonProperty(String) public firstName: string = ""; @jsonIgnore() public isExpanded: boolean = false; } JSON.stringify(new User());