0Pricing
Swift Academy · Leçon

encode(to:) et init(from:) manuels

Prenez le contrôle total de la logique de sérialisation.

encode(to:) et init(from:) manuels est une leçon Swift Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Swift Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Swift Academy comprend 4 leçons au total.

Quand la synthèse ne suffit pas

Parfois, la structure JSON ne correspond pas à vos propriétés : vous avez besoin de transformations calculées, de valeurs de repli par défaut ou d’un aplatissement. Vous devez alors implémenter manuellement encode(to:) et init(from:).

import Foundation

struct Temperature: Codable {
    var celsius: Double
}

print("Manual coding gives full control")

Déclarer CodingKeys en premier

Le codage manuel commence par une énumération CodingKeys. Les conteneurs de clés utilisent ces clés pour lire et écrire les valeurs.

import Foundation

struct User {
    var name: String
    var age: Int
    enum CodingKeys: String, CodingKey {
        case name
        case age
    }
}

print(User.CodingKeys.name.stringValue)

Implémenter init(from:)

init(from decoder:) obtient un conteneur de clés avec container(keyedBy:), puis décode chaque propriété à partir de sa clé.

import Foundation

struct User: Decodable {
    var name: String
    var age: Int
    enum CodingKeys: String, CodingKey { case name, age }
    init(from decoder: Decoder) throws {
        let c = try decoder.container(keyedBy: CodingKeys.self)
        name = try c.decode(String.self, forKey: .name)
        age = try c.decode(Int.self, forKey: .age)
    }
}

let u = try JSONDecoder().decode(User.self, from: "{\"name\":\"Ada\",\"age\":36}".data(using: .utf8)!)
print(u.name, u.age)

Implémenter encode(to:)

encode(to encoder:) obtient un conteneur de clés modifiable avec container(keyedBy:) et écrit chaque propriété avec encode(_:forKey:).

import Foundation

struct User: Encodable {
    var name: String
    var age: Int
    enum CodingKeys: String, CodingKey { case name, age }
    func encode(to encoder: Encoder) throws {
        var c = encoder.container(keyedBy: CodingKeys.self)
        try c.encode(name, forKey: .name)
        try c.encode(age, forKey: .age)
    }
}

let data = try JSONEncoder().encode(User(name: "Ada", age: 36))
print(String(data: data, encoding: .utf8)!)

Sérialisation complète écrite manuellement

L’implémentation des deux méthodes rend le type entièrement sérialisable, avec une logique personnalisée aux deux extrémités.

import Foundation

struct Point: Codable {
    var x: Int
    var y: Int
    enum CodingKeys: String, CodingKey { case x, y }
    init(x: Int, y: Int) { self.x = x; self.y = y }
    init(from d: Decoder) throws {
        let c = try d.container(keyedBy: CodingKeys.self)
        x = try c.decode(Int.self, forKey: .x)
        y = try c.decode(Int.self, forKey: .y)
    }
    func encode(to e: Encoder) throws {
        var c = e.container(keyedBy: CodingKeys.self)
        try c.encode(x, forKey: .x)
        try c.encode(y, forKey: .y)
    }
}

let back = try JSONDecoder().decode(Point.self, from: try JSONEncoder().encode(Point(x: 1, y: 2)))
print(back.x, back.y)

Fournir des valeurs par défaut

Utilisez decodeIfPresent avec l’opérateur de coalescence pour fournir une valeur par défaut lorsqu’une clé est absente, au lieu de lever une erreur.

import Foundation

struct Settings: Decodable {
    var theme: String
    enum CodingKeys: String, CodingKey { case theme }
    init(from decoder: Decoder) throws {
        let c = try decoder.container(keyedBy: CodingKeys.self)
        theme = try c.decodeIfPresent(String.self, forKey: .theme) ?? "light"
    }
}

let s = try JSONDecoder().decode(Settings.self, from: "{}".data(using: .utf8)!)
print(s.theme)

Transformer les valeurs

Le décodage manuel vous permet de transformer le JSON brut en une représentation plus riche — ici, une valeur d’entrée en Fahrenheit est stockée en Celsius.

import Foundation

struct Reading: Decodable {
    var celsius: Double
    enum CodingKeys: String, CodingKey { case fahrenheit }
    init(from decoder: Decoder) throws {
        let c = try decoder.container(keyedBy: CodingKeys.self)
        let f = try c.decode(Double.self, forKey: .fahrenheit)
        celsius = (f - 32) * 5 / 9
    }
}

let r = try JSONDecoder().decode(Reading.self, from: "{\"fahrenheit\":212}".data(using: .utf8)!)
print(r.celsius)

Aplatir un JSON imbriqué

Vous pouvez lire un conteneur imbriqué avec nestedContainer(keyedBy:forKey:) et faire remonter ses valeurs dans une structure Swift plate.

import Foundation

struct Profile: Decodable {
    var city: String
    enum Keys: String, CodingKey { case address }
    enum AddressKeys: String, CodingKey { case city }
    init(from decoder: Decoder) throws {
        let c = try decoder.container(keyedBy: Keys.self)
        let a = try c.nestedContainer(keyedBy: AddressKeys.self, forKey: .address)
        city = try a.decode(String.self, forKey: .city)
    }
}

let json = "{\"address\":{\"city\":\"Rome\"}}"
let p = try JSONDecoder().decode(Profile.self, from: json.data(using: .utf8)!)
print(p.city)

Encoder dans un conteneur imbriqué

L’encodage peut effectuer l’opération inverse : écrire une structure plate sous forme d’objet JSON imbriqué avec nestedContainer(keyedBy:forKey:).

import Foundation

struct Profile: Encodable {
    var city: String
    enum Keys: String, CodingKey { case address }
    enum AddressKeys: String, CodingKey { case city }
    func encode(to encoder: Encoder) throws {
        var c = encoder.container(keyedBy: Keys.self)
        var a = c.nestedContainer(keyedBy: AddressKeys.self, forKey: .address)
        try a.encode(city, forKey: .city)
    }
}

let data = try JSONEncoder().encode(Profile(city: "Rome"))
print(String(data: data, encoding: .utf8)!)

Valider pendant le décodage

Comme init(from:) n’est qu’un initialiseur, vous pouvez valider les valeurs et lever une erreur personnalisée lorsqu’elles sont hors limites.

import Foundation

struct Score: Decodable {
    var value: Int
    enum CodingKeys: String, CodingKey { case value }
    init(from decoder: Decoder) throws {
        let c = try decoder.container(keyedBy: CodingKeys.self)
        let v = try c.decode(Int.self, forKey: .value)
        guard (0...100).contains(v) else {
            throw DecodingError.dataCorruptedError(forKey: .value, in: c, debugDescription: "out of range")
        }
        value = v
    }
}

let s = try JSONDecoder().decode(Score.self, from: "{\"value\":80}".data(using: .utf8)!)
print(s.value)

Mélanger codage manuel et synthétisé

Un type peut implémenter manuellement une seule méthode et laisser le compilateur synthétiser l’autre — par exemple, utiliser un init(from:) personnalisé avec un encodage synthétisé.

import Foundation

struct Flag: Codable {
    var on: Bool
    enum CodingKeys: String, CodingKey { case on }
    init(from decoder: Decoder) throws {
        let c = try decoder.container(keyedBy: CodingKeys.self)
        on = (try? c.decode(Bool.self, forKey: .on)) ?? false
    }
    init(on: Bool) { self.on = on }
}

let data = try JSONEncoder().encode(Flag(on: true))
print(String(data: data, encoding: .utf8)!)

Vérification rapide : codage manuel

Vérifiez votre compréhension des méthodes de sérialisation écrites manuellement.

Récapitulatif : encode(to:) et init(from:) manuels

Vous avez appris à contrôler entièrement le codage :

  • Déclarez CodingKeys, puis implémentez init(from:) et encode(to:).
  • Utilisez container(keyedBy:) et encode/decode(_:forKey:).
  • decodeIfPresent associé à ?? fournit des valeurs par défaut ; nestedContainer permet d’aplatir ou d’imbriquer le JSON.
  • Vous pouvez valider et transformer les valeurs, ainsi que combiner des méthodes manuelles et synthétisées.

Questions Fréquemment Posées

La leçon « encode(to:) et init(from:) manuels » est-elle gratuite ?

Oui — le texte complet de « encode(to:) et init(from:) manuels » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Swift Academy, passe à CoddyKit PRO. Le cours Swift Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « encode(to:) et init(from:) manuels » ?

Prenez le contrôle total de la logique de sérialisation. Tu pratiques Swift Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Swift Academy ?

Aucune expérience préalable n'est requise. Swift Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.

Combien de temps prend la leçon « encode(to:) et init(from:) manuels » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Swift Academy ?

Oui. Chaque leçon Swift Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. CodingKeys pour renommer
  2. Stratégies de décodage des clés et des dates
  3. encode(to:) et init(from:) manuels
  4. Décodage de JSON hétérogène
← Retour à Swift Academy