العمل مع JSON في Swift: التحليل والتسلسل عمليًا
\n\nJSON (JavaScript Object Notation) هو تنسيق خفيف لتبادل البيانات أصبح المعيار الفعلي للتواصل بين العميل والخادم في تطوير تطبيقات الويب والجوال. في نظام Apple البيئي (iOS، macOS، watchOS، tvOS)، يتم العمل مع JSON عبر آليات مدمجة قوية. في هذه المقالة، سنشرح بالتفصيل كيفية تحليل وتسلسل JSON في Swift بأمثلة حقيقية، باستخدام كل من البروتوكول الحديث Codable والكلاسيكي JSONSerialization.
المقالة موجهة للمطورين الذين لديهم معرفة أساسية بـ Swift ويريدون العمل بثقة مع طلبات الشبكة والتخزين المحلي للبيانات بتنسيق JSON.
\n\n1. أساسيات JSON ومكانته في تطبيقات Swift
\n\nJSON هو تنسيق نصي يعتمد على هيكلين: الكائنات (مجموعة أزواج مفتاح-قيمة) والمصفوفات (قوائم مرتبة). في Swift، تقابل هذه الهياكل Dictionary و Array. أنواع البيانات في JSON محدودة: سلاسل نصية، أرقام، قيم منطقية، null، كائنات ومصفوفات.
السيناريو النموذجي لاستخدام JSON في تطبيق iOS/macOS يبدو كالتالي:
\n- \n
- الحصول على سلسلة JSON من الخادم (عبر URLSession). \n
- تحليل JSON إلى نماذج Swift (مثل الهياكل أو الفئات). \n
- معالجة البيانات وعرضها في الواجهة. \n
- تسلسل (تحويل عكسي) النماذج إلى JSON لإرسالها إلى الخادم. \n
توفر Apple طريقتين رئيسيتين للعمل مع JSON: JSONSerialization (منخفض المستوى ولكنه مرن) و Codable (عالي المستوى، آمن من حيث الأنواع، موصى به منذ Swift 4+).
2. تحليل JSON باستخدام Codable (الطريقة الموصى بها)
\n\nالبروتوكول Codable يجمع بين Encodable (للتسلسل) و Decodable (للتحليل). هذه هي الطريقة الأسهل والأكثر أمانًا للعمل مع JSON في Swift.
مثال 1: تحليل كائن JSON بسيط
\n\nلنفترض أن الخادم يعيد JSON التالي:
\n{\n "userId": 1,\n "id": 1,\n "title": "مثال مهمة",\n "completed": false\n}\n\nلننشئ هيكل النموذج المتوافق مع Codable:
struct TodoItem: Codable {\n let userId: Int\n let id: Int\n let title: String\n let completed: Bool\n}\n\nالآن سنقوم بتحليل سلسلة JSON:
\nlet jsonString = """\n{\n "userId": 1,\n "id": 1,\n "title": "مثال مهمة",\n "completed": false\n}\n"""\n\nif let jsonData = jsonString.data(using: .utf8) {\n let decoder = JSONDecoder()\n do {\n let todo = try decoder.decode(TodoItem.self, from: jsonData)\n print("المهمة: \\(todo.title)، مكتملة: \\(todo.completed)")\n } catch {\n print("خطأ في التحليل: \\(error.localizedDescription)")\n }\n}\n\nمثال 2: تحليل مصفوفة من الكائنات
\n\nإذا أعاد الخادم مصفوفة من المهام:
\n[\n {"userId": 1, "id": 1, "title": "مهمة 1", "completed": false},\n {"userId": 1, "id": 2, "title": "مهمة 2", "completed": true}\n]\n\nالتحليل يتم بنفس البساطة — نحتاج فقط إلى تحديد نوع المصفوفة:
\nlet todoArray = try decoder.decode([TodoItem].self, from: jsonData)\n\n2.1. المفاتيح المخصصة و snake_case
\n\nغالبًا ما يستخدم JSON تنسيق snake_case (مثل user_id)، بينما في Swift يُستخدم camelCase (userId). يمكن لـ JSONDecoder تحويل المفاتيح تلقائيًا:
decoder.keyDecodingStrategy = .convertFromSnakeCase\n\nإذا كنت بحاجة إلى تعيين تطابق غير قياسي، استخدم التعداد CodingKeys:
struct User: Codable {\n let fullName: String\n let emailAddress: String\n\n enum CodingKeys: