مقدمة: لماذا JSON مهم في Rust
\n\nJSON (JavaScript Object Notation) هو تنسيق خفيف لتبادل البيانات أصبح المعيار الفعلي لواجهات برمجة تطبيقات الويب (API)، وملفات التكوين، والتفاعل بين الخدمات. في Rust، لغة البرمجة النظامية التي تركز على الأمان والأداء، يتم تنفيذ العمل مع JSON من خلال نظام قوي من الكريتات (المكتبات).
\n\nعلى الرغم من أن Rust لا يحتوي على دعم مدمج لـ JSON (على عكس JavaScript أو Python)، فإن نظام الأنواع الخاص به وطريقة إدارة الذاكرة تجعل معالجة JSON ليس فقط آمنة، بل سريعة بشكل لا يصدق. في هذه المقالة، سنشرح كيفية تحليل JSON إلى هياكل Rust، وكيفية تسلسل البيانات مرة أخرى إلى JSON، وكيفية تجنب الأخطاء الشائعة للمبتدئين.
\n\nالأداة الرئيسية للعمل مع JSON في Rust هي الكريت serde (إطار التسلسل/إلغاء التسلسل) إلى جانب serde_json. توفر هذه المكتبات تجريدات بدون تكلفة (zero-cost abstractions) وتدعم هياكل البيانات المتداخلة المعقدة.
تثبيت وإعداد التبعيات
\n\nقبل البدء، قم بإنشاء مشروع Rust جديد وأضف التبعيات الضرورية إلى ملف Cargo.toml:
[dependencies]\nserde = { version = "1.0", features = ["derive"] }\nserde_json = "1.0"\n\nالعلامة features = ["derive"] للكريت serde تسمح باستخدام الماكرو #[derive(Serialize, Deserialize)]، الذي يقوم تلقائيًا بإنشاء الكود لتحويل هياكل البيانات الخاصة بك إلى JSON والعكس. هذه ميزة رئيسية في Rust - تكتب الحد الأدنى من الكود النمطي، ويتولى المترجم العمل الروتيني.
بعد إضافة التبعيات، نفذ cargo build لتحميل وتجميع المكتبات.
تحليل JSON إلى هياكل Rust (إلغاء التسلسل)
\n\nإنشاء نموذج البيانات
\n\nأول شيء يجب فعله هو تحديد هياكل Rust التي تتوافق مع بيانات JSON الخاصة بك. لنفترض أن لدينا JSON يمثل معلومات عن مستخدم:
\n\n{\n "name": "أليكسي",\n "age": 30,\n "email": "alexey@example.com",\n "is_active": true\n}\n\nلننشئ الهيكل المقابل ونضيف السمات للتسلسل:
\n\nuse serde::{Deserialize, Serialize};\n\n#[derive(Debug, Serialize, Deserialize)]\nstruct User {\n name: String,\n age: u32,\n email: String,\n is_active: bool,\n}\n\nالماكرو #[derive(Debug)] يسمح بطباعة الهيكل في وحدة التحكم لأغراض التصحيح. بدونه، لن تتمكن من استخدام println!("{:?}", user).
تحليل سلسلة JSON
\n\nالآن لنكتب دالة تأخذ سلسلة JSON وتعيد هيكل User:
fn parse_user(json_str: &str) -> Result<User, serde_json::Error> {\n let user: User = serde_json::from_str(json_str)?;\n Ok(user)\n}\n\nfn main() {\n let data = r#"\n {\n "name": "أليكسي",\n "age": 30,\n "email": "alexey@example.com",\n "is_active": true\n }\n "#;\n\n match parse_user(data) {\n Ok(user) => println!("المستخدم: {:?}", user),\n Err(e) => eprintln!("خطأ في التحليل: {}", e),\n }\n}\n\nالنقطة الأساسية: serde_json::from_str يقوم تلقائيًا بمطابقة حقول JSON مع حقول الهيكل. إذا كانت أسماء الحقول في JSON تختلف عن الأسماء في Rust (على سبيل المثال، JSON يستخدم snake_case بينما Rust يستخدم camelCase)، يمكن استخدام السمة #[serde(rename = "اسم_الحقل")].
معالجة الهياكل المتداخلة
\n\nغالبًا ما يحتوي JSON على كائنات متداخلة. لننظر إلى مثال مع عنوان المستخدم:
\n\n{\n "name": "أليكسي",\n "address": {\n "city": "موسكو",\n "street": "تفيرسكايا",\n "zip": "101000"\n }\n}\n\nلننشئ الهياكل المتداخلة:
\n\n#[derive(Debug, Serialize, Deserialize