تسلسل الكائنات في Rust: دليل شامل لمكتبة serde وصيغ البيانات
التسلسل هو عملية تحويل هياكل البيانات أو الكائنات إلى صيغة يمكن حفظها في ملف، أو نقلها عبر الشبكة، أو تخزينها مؤقتًا. في لغة Rust، يتم حل هذه المشكلة بأناقة وكفاءة باستخدام مكتبة serde (Serialization/Deserialization). في هذه المقالة، سنشرح بالتفصيل كيفية عمل التسلسل في Rust، وما هي صيغ البيانات المدعومة، وكيفية اختيار الأداة المناسبة لمشروعك.
ما هي serde ولماذا هي المعيار الفعلي؟
serde هو إطار عمل لتسلسل وإلغاء تسلسل هياكل البيانات في Rust.它不是 مرتبط بصيغة محددة — يمكنك استخدام JSON، Bincode، YAML، TOML، MessagePack، CBOR وغيرها الكثير. الفكرة الأساسية: تصف هيكلك مرة واحدة، وتقوم serde تلقائيًا بتوليد الكود للعمل مع أي صيغة من خلال نظام السمات Serialize و Deserialize.
مزايا serde:
- أداء أقصى — يتم توليد الكود في مرحلة الترجمة (zero-cost abstraction)
- أمان الأنواع — يتم اكتشاف أخطاء عدم تطابق الصيغ في مرحلة الترجمة
- دعم الهياكل المعقدة: enum، المتجهات، خرائط التجزئة، الكائنات المتداخلة
- إمكانية التخصيص من خلال السمات
التثبيت والإعداد الأساسي
أضف التبعيات التالية إلى Cargo.toml:
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"bincode = "1.3"النقطة الأساسية هي الميزة "derive" لـ serde. بدونها، ستحتاج إلى تنفيذ السمات Serialize و Deserialize يدويًا.
مثال بسيط: التسلسل إلى JSON
JSON هو الصيغة الأكثر شيوعًا لتطبيقات الويب وواجهات API. لنلق نظرة على مثال أساسي:
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]struct User { id: u32, name: String, email: String, is_active: bool,}
fn main() { let user = User { id: 42, name: "أليكسي".to_string(), email: "alex@example.com".to_string(), is_active: true, };
// التسلسل إلى JSON let json = serde_json::to_string(&user).unwrap(); println!("JSON: {}", json);
// إلغاء التسلسل من JSON let deserialized: User = serde_json::from_str(&json).unwrap(); println!("تم إلغاء التسلسل: {:?}", deserialized);}الإخراج:
JSON: {"id":42,"name":"أليكسي","email":"alex@example.com","is_active":true}تم إلغاء التسلسل: User { id: 42, name: "أليكسي", email: "alex@example.com", is_active: true }التسلسل الثنائي باستخدام bincode
للتطبيقات عالية الأداء (الألعاب، أنظمة الوقت الفعلي، قواعد البيانات) غالبًا ما تكون هناك حاجة إلى صيغة ثنائية مضغوطة. bincode هو أحد أفضل الخيارات:
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]struct GameState { level: u16, health: f32, inventory: Vec<String>, checkpoint: (f64, f64),}
fn main() { let state = GameState { level: 5, health: 87.5, inventory: vec!["سيف".into(), "جرعة".into()], checkpoint: (120.5, -34.8), };
// التسلسل إلى صيغة ثنائية let binary = bincode::serialize(&state).unwrap(); println!("الحجم الثنائي: {} بايت", binary.len());
// إلغاء التسلسل let restored: GameState = bincode::deserialize(&binary).unwrap(); println!("تم الاستعادة: {:?}", restored);}يمنحك Bincode مكسبًا في حجم البيانات وسرعة المعالجة مقارنة بـ JSON. على سبيل المثال، هيكل من 4 حقول سيشغل حوالي 40 بايت مقابل 100+ في JSON.
العمل مع YAML و TOML
للملفات التكوينية