encode(to:) e init(from:) manuales
Obtenga un control total sobre la lógica de serialización.
encode(to:) e init(from:) manuales es una lección gratuita de Swift Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Swift Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Swift Academy incluye 4 lecciones en total.
Cuando la síntesis no es suficiente
A veces la estructura de JSON no coincide con sus propiedades: necesita transformaciones calculadas, valores predeterminados alternativos o aplanamiento. En ese caso, debe implementar manualmente encode(to:) e init(from:).
import Foundation
struct Temperature: Codable {
var celsius: Double
}
print("Manual coding gives full control")Declaración inicial de CodingKeys
La codificación manual comienza con un enum CodingKeys. Los contenedores con claves utilizan estas claves para leer y escribir valores.
import Foundation
struct User {
var name: String
var age: Int
enum CodingKeys: String, CodingKey {
case name
case age
}
}
print(User.CodingKeys.name.stringValue)Implementación de init(from:)
init(from decoder:) obtiene un contenedor con claves mediante container(keyedBy:) y después decodifica cada propiedad usando su clave.
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)Implementación de encode(to:)
encode(to encoder:) obtiene un contenedor con claves modificable mediante container(keyedBy:) y escribe cada propiedad 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 de forma manual
Implementar ambos métodos hace que el tipo sea completamente Codable, con lógica personalizada en ambos sentidos.
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)Provisión de valores predeterminados
Use decodeIfPresent junto con el operador de fusión de nulos para proporcionar un valor predeterminado cuando falte una clave, en lugar de lanzar un error.
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)Transformación de valores
La decodificación manual permite transformar el JSON sin procesar en una representación más completa; en este caso, una entrada en grados Fahrenheit se almacena en grados 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)Aplanamiento de JSON anidado
Puede leer un contenedor anidado con nestedContainer(keyedBy:forKey:) y trasladar sus valores a una estructura Swift plana.
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)Codificación en un contenedor anidado
La codificación puede hacer lo contrario: escribir una estructura plana como un objeto JSON anidado mediante 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)!)Validación durante la decodificación
Como init(from:) es simplemente un inicializador, puede validar los valores y lanzar un error personalizado cuando estén fuera del rango permitido.
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)Combinación de métodos manuales y sintetizados
Un tipo puede implementar manualmente un solo método y dejar que el compilador sintetice el otro; por ejemplo, puede usar un init(from:) personalizado con una codificación sintetizada.
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)!)Comprobación rápida: codificación manual
Compruebe cuánto ha entendido sobre los métodos Codable escritos manualmente.
Resumen: encode(to:) e init(from:) manuales
Ha aprendido a controlar completamente la codificación:
- Declare
CodingKeysy después implementeinit(from:)yencode(to:). - Use
container(keyedBy:)yencode/decode(_:forKey:). decodeIfPresentjunto con??proporciona valores predeterminados;nestedContaineraplana o anida el JSON.- Puede validar y transformar datos, así como combinar métodos manuales y sintetizados.
Preguntas frecuentes
¿La lección «encode(to:) e init(from:) manuales» es gratis?
Sí — el texto completo de «encode(to:) e init(from:) manuales» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Swift Academy, actualiza a CoddyKit PRO. El curso de Swift Academy incluye 4 lecciones en total.
¿Qué aprenderé en «encode(to:) e init(from:) manuales»?
Obtenga un control total sobre la lógica de serialización. Practicas Swift Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Swift Academy?
No se requiere experiencia previa. Swift Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «encode(to:) e init(from:) manuales»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Swift Academy?
Sí. Cada lección de Swift Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- CodingKeys para cambiar nombres
- Estrategias de decodificación de claves y fechas
- encode(to:) e init(from:) manuales
- Decodificación de JSON heterogéneo