0Pricing
Swift Academy · Aula

encode(to:) e init(from:) Manuais

Assuma controle total da lógica de serialização.

encode(to:) e init(from:) Manuais é uma aula grátis de Swift Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Swift Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Swift Academy inclui 4 aulas no total.

Quando a síntese não é suficiente

Às vezes, a estrutura do JSON não corresponde às suas propriedades — você precisa de transformações calculadas, valores padrão ou achatamento. Nesse caso, implemente encode(to:) e init(from:) manualmente.

import Foundation

struct Temperature: Codable {
    var celsius: Double
}

print("Manual coding gives full control")

Declarando CodingKeys primeiro

A codificação manual começa com uma enumeração CodingKeys. Os contêineres de chaves usam essas chaves para ler e gravar valores.

import Foundation

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

print(User.CodingKeys.name.stringValue)

Implementando init(from:)

init(from decoder:) obtém um contêiner de chaves com container(keyedBy:) e depois decodifica cada propriedade usando sua chave.

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)

Implementando encode(to:)

encode(to encoder:) obtém um contêiner de chaves mutável com container(keyedBy:) e grava cada propriedade com 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

Implementar os dois métodos torna o tipo totalmente Codable, com lógica personalizada nas duas pontas.

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)

Fornecendo valores padrão

Utilize decodeIfPresent com o operador de coalescência de nulos para fornecer um valor padrão quando uma chave estiver ausente, em vez de lançar um erro.

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)

Transformando valores

A decodificação manual permite transformar JSON bruto em uma representação mais rica — aqui, uma entrada em Fahrenheit é armazenada como 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)

Achatando JSON aninhado

Você pode ler um contêiner aninhado com nestedContainer(keyedBy:forKey:) e elevar seus valores para uma estrutura 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)

Codificando em um contêiner aninhado

A codificação pode fazer o inverso: gravar uma estrutura plana como um objeto JSON aninhado 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)!)

Validando durante a decodificação

Como init(from:) é apenas um inicializador, você pode validar valores e lançar um erro personalizado quando eles estiverem fora do intervalo 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)

Combinando codificação manual e sintetizada

Um tipo pode implementar manualmente apenas um método e deixar o compilador sintetizar o outro — por exemplo, usar um init(from:) personalizado com a codificação 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)!)

Verificação rápida: codificação manual

Teste sua compreensão sobre métodos Codable escritos manualmente.

Recapitulação: encode(to:) e init(from:) manuais

Você aprendeu a ter controle total sobre a codificação:

  • Declare CodingKeys e implemente init(from:) e encode(to:).
  • Utilize container(keyedBy:) e encode/decode(_:forKey:).
  • decodeIfPresent junto com ?? fornece valores padrão; nestedContainer achata ou aninha JSON.
  • Você pode validar, transformar e combinar métodos manuais com métodos sintetizados.

Perguntas Frequentes

A aula “encode(to:) e init(from:) Manuais” é grátis?

Sim — o texto completo de “encode(to:) e init(from:) Manuais” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Swift Academy, atualize para CoddyKit PRO. O curso de Swift Academy inclui 4 aulas no total.

O que vou aprender em “encode(to:) e init(from:) Manuais”?

Assuma controle total da lógica de serialização. Você pratica Swift Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Swift Academy?

Nenhuma experiência prévia é necessária. Swift Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “encode(to:) e init(from:) Manuais”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Swift Academy?

Sim. Cada aula de Swift Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. CodingKeys para Renomeação
  2. Estratégias de Decodificação de Chaves e Datas
  3. encode(to:) e init(from:) Manuais
  4. Decodificação de JSON Heterogêneo
← Voltar para Swift Academy