سيرياليزيشن الكائنات في TypeScript: من JSON إلى protobuf
السيرياليزيشن هي عملية تحويل بنية بيانات معقدة (كائن، مصفوفة، مثيل فئة) إلى تنسيق مناسب للتخزين أو النقل عبر الشبكة. العملية العكسية - إلغاء السيرياليزيشن - تستعيد الكائن من هذا التنسيق. في TypeScript، الذي هو طبقة علوية صارمة الأنواع فوق JavaScript، تكتسب السيرياليزيشن أهمية خاصة: من المهم ليس فقط نقل البيانات، ولكن أيضًا الحفاظ على الأنواع والطرق وبنية الفئات.
في هذه المقالة، سنستعرض الأساليب والأدوات الرئيسية لسيرياليزيشن الكائنات في TypeScript، بدءًا من الأدوات المدمجة وصولاً إلى المكتبات المتخصصة.
1. السيرياليزيشن الأصلي: JSON.stringify و JSON.parse
الطريقة الأبسط والأكثر شيوعًا هي استخدام الطرق المدمجة JSON.stringify() و JSON.parse(). ومع ذلك، لهذا النهج قيود:
- لا يتم سيرياليزة الدوال،
undefined،Symbol،BigInt(في الإصدارات القديمة). - لا يتم الحفاظ على النموذج الأولي للكائن - عند إلغاء السيرياليزيشن ستحصل على كائن عادي، وليس مثيل فئة.
- المراجع الدائرية تسبب خطأ.
// مثال على سيرياليزيشن بسيطinterface User { id: number; name: string; email: string;}
const user: User = { id: 1, name: "إيفان", email: "ivan@example.com"};
const jsonString = JSON.stringify(user);console.log(jsonString); // {"id":1,"name":"إيفان","email":"ivan@example.com"}
const parsedUser: User = JSON.parse(jsonString);console.log(parsedUser.name); // إيفانبالنسبة للبيانات البسيطة، هذا كافٍ، ولكن إذا كنت بحاجة للعمل مع الفئات، فستحتاج إلى حل أكثر تقدمًا.
2. السيرياليزيشن المخصص باستخدام طرق toJSON و fromJSON
يسمح TypeScript (و JavaScript) بتعريف طريقة toJSON() في الفئة، والتي سيتم استدعاؤها أثناء السيرياليزيشن عبر JSON.stringify. لإلغاء السيرياليزيشن، يمكن إنشاء طريقة ثابتة fromJSON.
class Person { constructor( public firstName: string, public lastName: string, public age: number ) {}
// طريقة للسيرياليزيشن toJSON() { return { fullName: `${this.firstName} ${this.lastName}`, age: this.age }; }
// طريقة ثابتة لإلغاء السيرياليزيشن static fromJSON(json: any): Person { const [firstName, lastName] = json.fullName.split(' '); return new Person(firstName, lastName, json.age); }}
const person = new Person("آنا", "بتروفا", 30);const json = JSON.stringify(person);console.log(json); // {"fullName":"آنا بتروفا","age":30}
const restoredPerson = Person.fromJSON(JSON.parse(json));console.log(restoredPerson.firstName); // آنايمنحك هذا النهج تحكمًا كاملاً، ولكنه يتطلب كتابة كود نمطي لكل فئة.
3. مكتبة class-transformer
class-transformer هي واحدة من أشهر المكتبات للسيرياليزيشن/إلغاء السيرياليزيشن في TypeScript. تسمح بتحويل الكائنات العادية إلى مثيلات فئات والعكس باستخدام الديكورات.
التثبيت:
npm install class-transformer reflect-metadataمثال على الاستخدام:
import { plainToClass, classToPlain, Expose, Transform } from "class-transformer";import "reflect-metadata";
class Product { @Expose() id: number;
@Expose() name: string;
@Expose() @Transform(({ value }) => value.toUpperCase()) // تحويل مخصص category: string;
@Expose({ name: "price_with_tax" }) // إعادة تسمية الحقل price: number;
constructor(id: number, name: string, category: string, price: number) { this.id = id; this.name = name; this.category = category; this.price = price; }
getInfo(): string { return `${this.name} (${th