تسلسل الكائنات في Swift (iOS/macOS): Codable وJSON وPropertyList
التسلسل هو عملية تحويل كائنات البيانات إلى تنسيق مناسب للتخزين أو النقل (مثل JSON وXML وProperty List). في نظام Apple البيئي (iOS وmacOS وwatchOS وtvOS)، يوفر Swift آلية قوية وأنيقة للتسلسل وإلغاء التسلسل - بروتوكول Codable. في هذه المقالة، سنشرح بالتفصيل كيفية استخدام Codable وJSONEncoder وPropertyListEncoder ونظائرها للعمل مع البيانات.
ما هو Codable؟
Codable هو بروتوكول مركب يجمع بين Encodable (لتشفير الكائن إلى تنسيق خارجي) وDecodable (لفك التشفير من تنسيق خارجي إلى كائن). إذا كان الهيكل أو الفئة الخاصة بك في Swift تتوافق مع Codable، فستحصل تلقائيًا على القدرة على تسلسل وإلغاء تسلسلها.
الإعلان الأساسي:
struct User: Codable { let id: Int let name: String let email: String}جميع الأنواع القياسية في Swift (String وInt وDouble وBool وDate وData وURL وحتى الأنواع الاختيارية والمصفوفات/القواميس) تتوافق بالفعل مع Codable.
التشفير إلى JSON
لتشفير كائن إلى JSON، يُستخدم JSONEncoder. مثال:
let user = User(id: 1, name: "إيفان بيتروف", email: "ivan@example.com")let encoder = JSONEncoder()encoder.outputFormatting = .prettyPrinted // لإخراج جميل
do { let jsonData = try encoder.encode(user) if let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) }} catch { print("خطأ في التشفير: \\(error)")}النتيجة:
{ "id" : 1, "name" : "إيفان بيتروف", "email" : "ivan@example.com"}فك التشفير من JSON
للتحويل العكسي، يُستخدم JSONDecoder:
let jsonString = """{ "id": 2, "name": "ماريا سيدوروفا", "email": "maria@example.com"}"""let jsonData = Data(jsonString.utf8)let decoder = JSONDecoder()
do { let decodedUser = try decoder.decode(User.self, from: jsonData) print("تم فك تشفير المستخدم: \\(decodedUser.name)")} catch { print("خطأ في فك التشفير: \\(error)")}العمل مع Property List (plist)
لتسلسل إلى تنسيق XML Property List، يُستخدم PropertyListEncoder وPropertyListDecoder. هذا مفيد لتخزين البيانات في ملفات التكوين أو UserDefaults.
// التشفير إلى plistlet encoder = PropertyListEncoder()encoder.outputFormat = .xml
do { let plistData = try encoder.encode(user) // يمكن حفظ plistData في ملف أو UserDefaults} catch { print("خطأ في تشفير plist: \\(error)")}
// فك التشفير من plistlet decoder = PropertyListDecoder()do { let decodedUser = try decoder.decode(User.self, from: plistData) print(decodedUser)} catch { print("خطأ في فك تشفير plist: \\(error)")}المفاتيح المخصصة (CodingKeys)
أحيانًا لا تتطابق أسماء الخصائص في Swift مع المفاتيح في JSON. لهذا، يُستخدم التعداد CodingKeys:
struct Product: Codable { let productId: Int let productName: String let price: Double
enum CodingKeys: String, CodingKey { case productId = "product_id" case productName = "product_name" case price }}الآن، سيتم معالجة JSON الذي يحتوي على مفاتيح product_id وproduct_name بشكل صحيح.
معالجة التواريخ والأنواع الخاصة الأخرى
افتراضيًا، يقوم JSONEncoder وJSONDecoder بتشفير التواريخ كـ TimeInterval