Published on

Swift-da Codable, Decodable va Encodable protokollari

Authors

Bu video keyingi videolar uchun tayyorlov — internetdan ma'lumot yuklab, ilovada ishlatish. Internetdan kelgan ma'lumot bevosita ishlatib bo'lmaydi — avval decode qilish kerak. Bu videoda qo'lda decode qilishdan boshlab, Codable protokoligacha bosqichma-bosqich ko'rib chiqiladi.


Boshlang'ich model va ViewModel

struct CustomerModel: Identifiable {
    let id: String
    let name: String
    let points: Int
    let isPremium: Bool
}

class CodableViewModel: ObservableObject {
    @Published var customer: CustomerModel? = nil

    init() {
        getData()
    }

    func getData() { }
}

JSON data nima?

Internetdan kelgan ma'lumot odatda JSON formatida bo'ladi. JSON — matn ko'rinishidagi ma'lumot. Masalan:

{"id":"12345","name":"Joe","points":5,"isPremium":true}

Bu ilovaga Data (baytlar) sifatida keladi. Ularni to'g'ridan-to'g'ri ekranda ko'rsatib bo'lmaydi — avval CustomerModel-ga aylantirish kerak.


Soxta JSON data yaratish (test uchun)

Haqiqiy internet yuklamasi o'rniga, qanday ko'rinishini ko'rsatish uchun soxta JSON:

func getJsonData() -> Data? {
    let dictionary: [String: Any] = [
        "id": "12345",
        "name": "Joe",
        "points": 5,
        "isPremium": true
    ]
    return try? JSONSerialization.data(withJSONObject: dictionary, options: [])
}

1-bosqich: Qo'lda decode qilish (Codable-siz)

func getData() {
    guard let data = getJsonData() else { return }

    // Data → local object
    guard let localData = try? JSONSerialization.jsonObject(with: data, options: []),
          let dictionary = localData as? [String: Any],
          let id = dictionary["id"] as? String,
          let name = dictionary["name"] as? String,
          let points = dictionary["points"] as? Int,
          let isPremium = dictionary["isPremium"] as? Bool
    else { return }

    let newCustomer = CustomerModel(
        id: id,
        name: name,
        points: points,
        isPremium: isPremium
    )
    self.customer = newCustomer
}

Bu ishlaydi, lekin muammo bor: har bir o'zgaruvchini qo'lda yozish kerak. Model 20 ta xususiyat bo'lsa — 20 ta satr. Har safar xususiyat qo'shilganda — decode-ni ham yangilash kerak.


2-bosqich: Decodable protokoli

Decodable — modelni JSON-dan avtomatik yaratish imkonini beradi. Buning uchun ikkita narsa kerak:

1. CodingKeys — kalitlarni belgilash

struct CustomerModel: Identifiable, Decodable {
    let id: String
    let name: String
    let points: Int
    let isPremium: Bool

    // JSON kalit nomlari
    enum CodingKeys: String, CodingKey {
        case id
        case name
        case points
        case isPremium
        // JSON-da "isPremium" deb kelsa — shu nomlar mos kelishi shart
    }

    // Agar JSON-da boshqa nom bo'lsa, raw value bilan moslash:
    // case isPremium = "is_premium"  // JSON-da "is_premium" deb kelsa
}

2. init(from decoder:) — decode initsializatori

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)

    // Har bir xususiyatni tur bilan decode qilish
    self.id        = try container.decode(String.self, forKey: .id)
    self.name      = try container.decode(String.self, forKey: .name)
    self.points    = try container.decode(Int.self,    forKey: .points)
    self.isPremium = try container.decode(Bool.self,   forKey: .isPremium)
}

JSONDecoder bilan bir qatorli foydalanish

func getData() {
    guard let data = getJsonData() else { return }

    // Barcha manual decode o'rniga — bitta qator
    self.customer = try? JSONDecoder().decode(CustomerModel.self, from: data)
}

3-bosqich: Encodable protokoli

Encodable — aksincha: modelni JSON data-ga aylantirish. Server-ga ma'lumot yuborish kerak bo'lganda ishlatiladi.

struct CustomerModel: Identifiable, Decodable, Encodable {
    // ...

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)

        try container.encode(id,        forKey: .id)
        try container.encode(name,      forKey: .name)
        try container.encode(points,    forKey: .points)
        try container.encode(isPremium, forKey: .isPremium)
    }
}

JSONEncoder bilan foydalanish

// Dictionary → JSON Data o'rniga
let customer = CustomerModel(id: "111", name: "Emily", points: 100, isPremium: false)
let jsonData = try? JSONEncoder().encode(customer)
// Bu jsonData endi serverga yuborish uchun tayyor

4-bosqich: Codable = Decodable + Encodable

// Decodable + Encodable = Codable
struct CustomerModel: Identifiable, Codable {
    let id: String
    let name: String
    let points: Int
    let isPremium: Bool
}

Codable qo'llanganda, CodingKeys, init(from decoder:) va encode(to encoder:) funksiyalarini yozish shart emas — Swift bularni avtomatik bajaradi.

// Decode — bir qator
let customer = try? JSONDecoder().decode(CustomerModel.self, from: data)

// Encode — bir qator
let jsonData = try? JSONEncoder().encode(customer)

Qachon qo'lda decode kerak?

Codable barcha ishni avtomatik qiladi, lekin ba'zan qo'lda yozish kerak bo'ladi:

// JSON-da kalit nomi Swift-dagi nomdan farq qilsa
enum CodingKeys: String, CodingKey {
    case id
    case name
    case points
    case isPremium = "is_premium"  // JSON-da "is_premium", model-da isPremium
}

Bu holda faqat CodingKeys yoziladi — init(from:) va encode(to:) esa avtomatik ishlaydi.


Xulosa

JSON DataDecodeCustomerModel  (JSONDecoder)
CustomerModelEncodeJSON Data  (JSONEncoder)

Decodable  — decode imkoni (JSONModel)
Encodable  — encode imkoni (ModelJSON)
Codableikkalasi (Decodable + Encodable)
Qo'ldaDecodable/EncodableCodable
Kod miqdoriKo'pO'rtachaMinimal
MoslashuvchanlikTo'liqTo'liqMos kalit nomlar uchun yetarli
TavsiyaYo'qMaxsus hollardaKo'pincha yetarli

Keyingi videoda Codable protokolidan foydalanib, haqiqiy API-dan ma'lumot yuklab olamiz.

Buy mea coffee