Codable & JSON
Convert between Swift values and JSON with almost no boilerplate. Mark a type Codable , then use JSONDecoder to read JSON and JSONEncoder to write it — with CodingKeys for when the names don't match.
Learn Codable & JSON in our free Swift course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Swift course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
- • What Codable , Encodable , and Decodable are
- • Decode JSON into a struct with JSONDecoder
- • Encode a struct to JSON with JSONEncoder
- • Map mismatched key names with CodingKeys
- • Handle snake_case with .convertFromSnakeCase
- • Decode optional/missing fields safely
1️⃣ Decoding JSON into a Struct
Describe the JSON's shape with a Codable struct, then let JSONDecoder fill it in. Every property must match a JSON key with a compatible type.
2️⃣ Encoding a Struct to JSON
Going the other way, JSONEncoder turns a Swift value into JSON Data . Set outputFormatting = .prettyPrinted for readable output.
3️⃣ CodingKeys and snake_case
When JSON keys don't match your property names, add a CodingKeys enum ( String, CodingKey ) to map them. For whole-model snake_case, a single .convertFromSnakeCase strategy does it automatically.
Your turn. Fill in the protocol and the decode method.
Pro Tips
- 💡 Mirror the JSON exactly. Match every key name and type, or decoding throws.
- 💡 Use Optionals for "maybe missing" fields so an absent key becomes nil instead of an error.
- 💡 Prefer .convertFromSnakeCase over hand-writing CodingKeys when the only difference is casing.
- 💡 Conform to just Decodable if you only ever read JSON — you don't always need both directions.
Common Errors (and the fix)
- "keyNotFound": a property has no matching JSON key. Fix the name, add CodingKeys , or make it Optional.
- "typeMismatch": the JSON value's type differs from your property. Match the real type (e.g. the JSON has a string, not an Int).
- "dataCorrupted" / invalid JSON: the input isn't valid JSON. Check the source bytes.
- Forgot import Foundation : JSONDecoder / Data live in Foundation — import it.
📋 Quick Reference
Task
Code
Enable JSON mapping
struct T: Codable { … }
Decode
JSONDecoder().decode(T.self, from: data)
Encode
JSONEncoder().encode(value)
Map key names
enum CodingKeys: String, CodingKey
snake_case
decoder.keyDecodingStrategy = .convertFromSnakeCase
Pretty JSON
encoder.outputFormatting = .prettyPrinted
Frequently Asked Questions
Mini-Challenge: Round-Trip a Model
No blanks this time — just a brief and an outline. Encode a value to JSON and decode it back to prove both directions work.
Practice quiz
What is Codable in Swift?
- A networking library
- A UI component
- A type alias for Encodable & Decodable, enabling JSON conversion
- A kind of optional
Answer: A type alias for Encodable & Decodable, enabling JSON conversion. Codable is a typealias combining Encodable and Decodable, so a Codable type can be both encoded and decoded.
Which protocol lets a type be turned INTO JSON (or other data)?
- Encodable
- Decodable
- Hashable
- Identifiable
Answer: Encodable. Encodable is the protocol for encoding a Swift value out to a format like JSON.
Which protocol lets JSON be turned INTO a Swift value?
- Encodable
- Comparable
- Equatable
- Decodable
Answer: Decodable. Decodable is the protocol for decoding data into a Swift value.
Which type encodes a Swift value to JSON data?
- JSONDecoder
- JSONEncoder
- JSONSerializer
- Data
Answer: JSONEncoder. JSONEncoder().encode(value) produces JSON Data from an Encodable value.
Which type decodes JSON data into a Swift value?
- JSONDecoder
- JSONEncoder
- JSONParser
- Codable
Answer: JSONDecoder. JSONDecoder().decode(T.self, from: data) builds a value of type T from JSON Data.
What is the purpose of a CodingKeys enum in a Codable type?
- To list errors
- To sort properties
- To map Swift property names to differently-named JSON keys
- To make properties optional
Answer: To map Swift property names to differently-named JSON keys. CodingKeys maps each property to its JSON key, useful when names differ (e.g. JSON first_name vs Swift firstName).
What must CodingKeys conform to?
- Int
- String, CodingKey (typically String-backed and CodingKey)
- Decodable only
- Any
Answer: String, CodingKey (typically String-backed and CodingKey). A CodingKeys enum is usually 'String, CodingKey', mapping property names to string keys.
How can you decode snake_case JSON keys into camelCase properties without writing CodingKeys?
- It is impossible
- Use JSONEncoder
- Mark properties weak
- Set decoder.keyDecodingStrategy = .convertFromSnakeCase
Answer: Set decoder.keyDecodingStrategy = .convertFromSnakeCase. .convertFromSnakeCase automatically maps first_name to firstName for the whole response.
If a JSON field might be absent, how should the matching Swift property be declared?
- As an Int
- As an Optional (e.g. String?) so a missing key decodes to nil
- As private
- As a constant
Answer: As an Optional (e.g. String?) so a missing key decodes to nil. Optional properties decode to nil when their key is missing, avoiding a keyNotFound error.
What does JSONEncoder's outputFormatting = .prettyPrinted do?
- Compresses the JSON
- Encrypts the JSON
- Produces human-readable, indented JSON
- Sorts keys alphabetically only
Answer: Produces human-readable, indented JSON. .prettyPrinted formats the encoded JSON with indentation and line breaks for readability.
Continue this course
- Previous: Concurrency: async/await
- Next: The Result Type