Almost every app talks to a JSON API, and Codable turns that into a few lines of type-safe code.
Codable is a typealias for Encodable & Decodable. When all stored properties are themselves Codable, the compiler synthesizes the encoding and decoding code — you just declare conformance.
Decode with JSONDecoder().decode(User.self, from: data) and encode with JSONEncoder().encode(value). Both throw on invalid or mismatched data, so they're called with try. The errors (DecodingError.keyNotFound, .typeMismatch...) describe exactly which path failed.
Mapping JSON to Swift:
- Optional properties may be missing or
null; non-optional ones are required. - Arrays and nested objects map to arrays and nested Codable types.
- Rename keys with a nested
enum CodingKeys: String, CodingKey { case id, fullName = "full_name" }— every property you want coded must be listed. - Or set
decoder.keyDecodingStrategy = .convertFromSnakeCaseto mapfull_nametofullNameglobally. - Dates need a strategy, e.g.
decoder.dateDecodingStrategy = .iso8601. encoder.outputFormatting = [.prettyPrinted, .sortedKeys]for readable output.
For unusual shapes, implement init(from decoder: Decoder) yourself using a keyed container: let c = try decoder.container(keyedBy: CodingKeys.self) and try c.decodeIfPresent(...).
Enums with raw values are Codable out of the box; enums with associated values get a synthesized keyed format.
Example
import Foundation
struct User: Codable {
let id: Int
let fullName: String
let email: String?
let roles: [String]
}
let json = Data("""
{"id": 7, "full_name": "Ana Ruiz", "roles": ["admin"]}
""".utf8)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let user = try decoder.decode(User.self, from: json)
print(user.fullName, user.email as Any) // Ana Ruiz nil
let encoder = JSONEncoder()
encoder.outputFormatting = .sortedKeys
print(String(decoding: try encoder.encode(user), as: UTF8.self))
// {"fullName":"Ana Ruiz","id":7,"roles":["admin"]}
} catch {
print("decode failed:", error)
}Remember
- Declare
Codableand the compiler writes the coding code - Rename keys with
CodingKeysor a key strategy - Non-optional properties are required in the JSON
Watch out for
- Declaring a field non-optional when the API sometimes omits it, so the whole decode fails.