ليه Codable؟
أي تطبيق حقيقي يتبادل بيانات مع سيرفر بصيغة JSON. بروتوكول Codable (وهو دمج لبروتوكولَي Encodable و Decodable) يجعل Swift يحوّل هياكلك من وإلى JSON تلقائيًا، دون كتابة كود تحويل يدويًا.
تبنّي Codable
struct User: Codable {
let id: Int
let name: String
let email: String
}
بما أن كل خاصية (Int, String) تتوافق مع Codable أصلًا، Swift يولّد كود الترميز والفكّ تلقائيًا — لا حاجة لكتابة أي شيء إضافي.
فكّ JSON إلى نوع Swift: JSONDecoder
let json = """
{ "id": 1, "name": "براء", "email": "b@example.com" }
""".data(using: .utf8)!
let decoder = JSONDecoder()
do {
let user = try decoder.decode(User.self, from: json)
print(user.name) // براء
} catch {
print("فشل الفكّ: \(error)")
}
decode دالة throws، لذا تُستدعى دائمًا داخل do/try/catch (راجع درس معالجة الأخطاء).
تحويل Swift إلى JSON: JSONEncoder
let newUser = User(id: 2, name: "سارة", email: "s@example.com")
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
if let data = try? encoder.encode(newUser) {
print(String(data: data, encoding: .utf8)!)
}
مفاتيح مختلفة الاسم: CodingKeys
لو كان اسم الحقل في JSON مختلفًا عن اسم الخاصية في Swift (مثلًا snake_case مقابل camelCase)، عرّف تعدادًا خاصًا:
struct Product: Codable {
let id: Int
let productName: String
enum CodingKeys: String, CodingKey {
case id
case productName = "product_name" // المفتاح الفعلي في JSON
}
}
💡
CodingKeysتعدادٌ من نوعStringيطابق أسماء خصائصك. انتبه: متى عرّفته، يجب أن يضم كل الخصائص التي تريد ترميزها، حتى التي لا تحتاج إعادة تسمية (مثلcase idأعلاه).
لو كانت كل مفاتيح الـ API بصيغة snake_case، لا داعي لـ CodingKeys في كل نوع: اضبط المحوّل مرة واحدة:
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase // product_name → productName
أخطاء شائعة
- مفتاح ناقص أو اسم مختلف بلا
CodingKeys: الفكّ يفشل وقت التشغيل بخطأkeyNotFound. إذا كان الحقل قد يغيب فعلًا من الـ JSON، اجعل الخاصية اختيارية (let email: String?). - نوع لا يطابق: الـ API يرسل
"id": "42"(نص) وخاصيتكInt→ خطأtypeMismatch. - ابتلاع الخطأ بـ
try?: يحوّل كل فشل إلىnilبدون أي تفاصيل. أثناء التطوير استخدمdo/catchواطبعerrorلتعرف أي مفتاح فشل.
Codable مع مصفوفات ومصفوفات متداخلة
struct Order: Codable {
let id: Int
let items: [String]
let customer: User // نوع Codable آخر متداخل — يعمل تلقائيًا
}
طالما كل نوع متداخل يتبنّى Codable، الفكّ والترميز يعملان في كل المستويات دون كود إضافي.
🎯 التالي: خلاصة المسار.