encode(to:) e init(from:) manuali
Assumi il pieno controllo della logica di serializzazione.
encode(to:) e init(from:) manuali è una lezione Swift Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Swift Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Swift Academy include 4 lezioni in totale.
Quando la sintesi non basta
A volte la struttura JSON non corrisponde alle proprietà: potrebbe essere necessario eseguire trasformazioni calcolate, fornire valori predefiniti o appiattire la struttura. In questi casi, implementate manualmente encode(to:) e init(from:).
import Foundation
struct Temperature: Codable {
var celsius: Double
}
print("Manual coding gives full control")Dichiarare prima CodingKeys
La codifica manuale inizia con un'enum CodingKeys. I keyed container usano queste chiavi per leggere e scrivere i valori.
import Foundation
struct User {
var name: String
var age: Int
enum CodingKeys: String, CodingKey {
case name
case age
}
}
print(User.CodingKeys.name.stringValue)Implementare init(from:)
init(from decoder:) ottiene un keyed container con container(keyedBy:), quindi decodifica ogni proprietà usando la relativa chiave.
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)Implementare encode(to:)
encode(to encoder:) ottiene un keyed container modificabile con container(keyedBy:) e scrive ogni proprietà con 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)!)Codable completo manualmente
Implementando entrambi i metodi, il tipo diventa completamente Codable, con una logica personalizzata in entrambe le direzioni.
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)Fornire valori predefiniti
Usate decodeIfPresent con l'operatore di coalescenza dei valori nulli per fornire un valore predefinito quando manca una chiave, invece di generare un errore.
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)Trasformare i valori
La decodifica manuale consente di trasformare il JSON grezzo in una rappresentazione più ricca: in questo caso, un valore in Fahrenheit viene memorizzato in 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)Appiattire il JSON annidato
È possibile leggere un container annidato con nestedContainer(keyedBy:forKey:) e portare i suoi valori al livello di una struct Swift piatta.
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)Codificare in un container annidato
La codifica può eseguire l'operazione inversa: scrivere una struct piatta come oggetto JSON annidato usando 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)!)Convalidare durante la decodifica
Poiché init(from:) è semplicemente un inizializzatore, è possibile convalidare i valori e generare un errore personalizzato quando non rientrano nell'intervallo consentito.
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)Combinare metodi manuali e sintetizzati
Un tipo può implementare manualmente un solo metodo e lasciare che il compilatore sintetizzi l'altro, ad esempio usando un init(from:) personalizzato con la codifica sintetizzata.
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)!)Verifica rapida: codifica manuale
Verificate la vostra comprensione dei metodi Codable scritti manualmente.
Riepilogo: encode(to:) e init(from:) manuali
Avete imparato ad avere il pieno controllo della codifica:
- Dichiarate
CodingKeys, quindi implementateinit(from:)eencode(to:). - Usate
container(keyedBy:)eencode/decode(_:forKey:). decodeIfPresentinsieme a??fornisce valori predefiniti;nestedContainerappiattisce o annida il JSON.- È possibile convalidare e trasformare i valori, oltre a combinare metodi manuali e sintetizzati.
Domande Frequenti
La lezione «encode(to:) e init(from:) manuali» è gratuita?
Sì — il testo completo di «encode(to:) e init(from:) manuali» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Swift Academy, passa a CoddyKit PRO. Il corso Swift Academy include 4 lezioni in totale.
Cosa imparerò in «encode(to:) e init(from:) manuali»?
Assumi il pieno controllo della logica di serializzazione. Eserciti Swift Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Swift Academy?
Non è richiesta alcuna esperienza precedente. Swift Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «encode(to:) e init(from:) manuali»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Swift Academy?
Sì. Ogni lezione Swift Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- CodingKeys per rinominare
- Strategie di decodifica per chiavi e date
- encode(to:) e init(from:) manuali
- Decodifica di JSON eterogenei