Skip to content
Prepare to Grow

Swift Fundamentals

Codable and JSON

Convert Swift models to and from JSON safely with Codable, coding keys, nested containers, and decoding strategies.

Beginner6 min read2 guided activities

Before you begin

What you will understand

  • Explain Encodable, Decodable, and Codable.
  • Decode JSON data into type-safe Swift models.
  • Map JSON field names with CodingKeys.
  • Handle optional, nested, malformed, and date values responsibly.
01

Learning stage

Concept Explanation

Codable combines Encodable and Decodable. When a model's stored properties also conform, Swift can usually synthesize the code required to convert between that model and an external representation such as JSON. JSONDecoder creates Swift values from Data, while JSONEncoder produces Data from Swift values.

Your model should describe the contract you actually expect. Use CodingKeys when external names differ from Swift naming, optionals only when a field may legitimately be absent or null, and custom decoding when the payload cannot be represented safely by synthesis. Decoding can throw, so inspect and preserve useful errors instead of silently replacing invalid data.

  • Decodable: creates a Swift value from an external representation.
  • Encodable: converts a Swift value into an external representation.
  • Codable: the combination of Encodable and Decodable.
  • CodingKeys: maps model properties to external field names.
  • Decoder strategies: configure dates, keys, and other representation choices.
02

Learning stage

Syntax & Examples

The model maps snake-case JSON to Swift-style property names and decodes the timestamp with an explicit strategy.

Course.swiftswift
import Foundation

struct Course: Codable {
  let id: Int
  let title: String
  let publishedAt: Date
  let instructor: Instructor?

  enum CodingKeys: String, CodingKey {
    case id, title, instructor
    case publishedAt = "published_at"
  }
}

struct Instructor: Codable {
  let name: String
}

let json = #"{"id":7,"title":"Swift Fundamentals","published_at":"2026-10-25T09:30:00Z","instructor":{"name":"Mina"}}"#
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601

do {
  let course = try decoder.decode(Course.self, from: Data(json.utf8))
  print(course.title)
} catch {
  print("Unable to decode course: (error)")
}
Expected output: “Swift Fundamentals”. The model keeps the external naming and date format at the decoding boundary.
03

Learning stage

Real-World Usage

These concepts appear throughout production iOS code. Focus on the requirement each technique communicates.

  • Decode API responses into domain or transport models.
  • Encode request bodies and locally persisted settings.
  • Represent nested resources, optional fields, and lists safely.
  • Configure date and key strategies for a documented service contract.
04

Learning stage

Common Mistakes

Notice these mistakes early so the compiler and type system can help instead of becoming obstacles.

  • Making every property optional merely to prevent decoding failures.
  • Using try? and losing the decoding error needed to diagnose a contract mismatch.
  • Assuming a server date is ISO 8601 without confirming its format.
  • Coupling UI-specific models directly to a large unstable network payload.
  • Treating null, a missing key, an empty string, and an empty collection as equivalent.
05

Learning stage

Practice Exercises

Work through these activities in a small Xcode project. No embedded playground is required on this site.

Activity 1

Decode a nested profile

Create Codable Profile and Address models, then decode JSON containing a nested address and an optional biography.

Hint: Make a property optional only when the payload contract permits absence or null.

Activity 2

Map external field names

Decode first_name, last_name, and created_at into Swift-style property names. Configure a suitable date strategy.

Hint: Use CodingKeys for names and configure the JSONDecoder before decoding.

06

Learning stage

Knowledge Check

Answer each question before revealing the explanation.

QUESTION 1

What does Codable represent?

  1. A.Encodable and Decodable together
  2. B.JSON only
  3. C.A collection type
  4. D.A networking client
Reveal answer

Encodable and Decodable together

Codable is a type alias combining both conversion directions; it is not limited to JSON.

QUESTION 2

What normally happens when a required non-optional property is missing from JSON?

Reveal answer

Decoding throws an error, commonly a keyNotFound DecodingError.

A missing required field violates the model's declared decoding contract.

07

Learning stage

Interview Preparation

Explain the idea in terms of its purpose, behavior, and tradeoffs rather than reciting syntax.

Should every property in a Decodable API model be optional?

Short answer: No. Optionality should match the service contract and the domain meaning of absence.

Explore the detailed answer

Making everything optional hides contract regressions and spreads uncertainty throughout the app. Required fields should fail decoding when missing. Optional fields are appropriate when null or absence is a valid response. At an API boundary, transport models can be validated and mapped into stronger domain models.

Possible follow-ups

  • • How do you inspect a DecodingError?
  • • When would you implement init(from:) manually?
08

Learning stage

Key Takeaways

Codable connects external data with Swift's type system. Model the real contract, configure representation strategies explicitly, and treat decoding failures as useful evidence rather than something to hide.

  • Codable combines Encodable and Decodable.
  • JSONEncoder and JSONDecoder work with Data.
  • CodingKeys maps external and Swift property names.
  • Optionality should represent valid absence, not suppress errors.
  • Date, key, and custom decoding strategies belong at the data boundary.