مقدمة إلى JSON في Rust
JSON (JavaScript Object Notation) يظل أحد أكثر تنسيقات تبادل البيانات شيوعًا في تطوير الويب وملفات التكوين وAPI. لغة Rust، المعروفة بأدائها وأمان الذاكرة، توفر أدوات قوية للعمل مع JSON من خلال كريت serde_json. في هذه المقالة، سنشرح بالتفصيل كيفية إجراء تحليل (Parsing) وتسلسل (Serialization) JSON في Rust باستخدام الأساليب الحديثة وأفضل الممارسات.
مكتبة serde (Serialization/Deserialization framework) هي المعيار الفعلي للعمل مع تنسيقات البيانات في نظام Rust البيئي. بالاقتران مع serde_json، تتيح تحويل هياكل Rust إلى JSON والعكس بسهولة.
إعداد المشروع وتثبيت التبعيات
للبدء، أنشئ مشروع Cargo جديد وأضف التبعيات اللازمة في ملف Cargo.toml:
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"العلامة features = ["derive"] لكريت serde تفعّل الماكرو #[derive(Serialize, Deserialize)] الذي يولد تلقائيًا كود التسلسل وإلغاء التسلسل للهياكل.
أساسيات تحليل JSON في Rust
تحليل سلسلة JSON إلى قيمة ديناميكية
أبسط طريقة لتحليل JSON هي استخدام النوع serde_json::Value، الذي يمثل قيمة JSON عامة:
use serde_json::Value;
fn main() { let data = r#" { "name": "أليكسي", "age": 30, "is_student": false, "hobbies": ["قراءة", "برمجة", "دراجة"] }"#;
let parsed: Value = serde_json::from_str(data).expect("خطأ في تحليل JSON"); println!("الاسم: {}", parsed["name"]); println!("العمر: {}", parsed["age"]); println!("طالب: {}", parsed["is_student"]); println!("الهواية الأولى: {}", parsed["hobbies"][0]);}النوع Value هو تعداد (enum) يمكن أن يحتوي على Null أو Bool أو Number أو String أو Array أو Object. هذا مناسب للنمذجة السريعة، لكن في كود الإنتاج من الأفضل استخدام هياكل محددة الأنواع.
تحليل JSON إلى هياكل محددة الأنواع
للعمل الآمن مع البيانات، حدد هيكلًا يتوافق مع مخطط JSON واستخدم ماكرو serde:
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]struct Person { name: String, age: u32, is_student: bool, hobbies: Vec<String>,}
fn main() { let json_str = r#" { "name": "ماريا", "age": 25, "is_student": true, "hobbies": ["رسم", "موسيقى"] }"#;
let person: Person = serde_json::from_str(json_str) .expect("خطأ في إلغاء التسلسل"); println!("{:?}", person); println!("{} تدرس: {}", person.name, person.is_student);}ميزة هذا النهج هي أن المترجم يتحقق من الأنواع في وقت الترجمة، مما يمنع أخطاء وقت التشغيل المرتبطة بالوصول غير الصحيح إلى الحقول.
تسلسل البيانات إلى JSON
تحويل الهياكل إلى سلسلة JSON
يتم التسلسل باستخدام الدالة serde_json::to_string():
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]struct Product { id: u64, name: String, price: f64, in_stock: bool,}
fn main() { let product = Product { id: 42, name: "حاسوب محمول".to_string(), price: 89999.99, in_stock: true, };
let json_string = serde_json::to_string(&product) .expect("خطأ في التسلسل"); println!("JSON: {}", json_string); // إخراج منسق مع ت