Skip to Content
Course content

53: Building a Small Data Model with Codable

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Imagine you've just ordered a complex piece of furniture from IKEA. When the delivery truck arrives, you don't get a fully assembled bookshelf; you get a flat-pack box. Inside that box, everything is compressed, packed tightly, and described by a set of instructions. To actually use the bookshelf in your room, you have to "decode" those instructions and assemble the raw parts into a physical structure that makes sense in your environment.

In Swift, JSON is that flat-pack box. It's a great way to transport data over the internet because it's lightweight and text-based, but you can't really "do" much with a raw JSON string in your app logic. You need to turn that string into a Swift object—like a Struct—so you can access properties with dot notation and get the benefit of type safety. That's exactly what the Codable protocol does; it's the assembly manual that tells Swift how to map the raw data in the box to the actual object in your code.

Translating JSON into Swift Types

Let's say we're building a movie tracking app. The API sends us a movie object that looks like this:

{
    "title": "Inception",
    "release_year": 2010,
    "is_classic": true
}

To handle this, we create a Struct that mirrors this shape. By conforming to Codable (which is actually just a shorthand for Encodable and Decodable), we tell Swift that this type is capable of being converted to and from a data format like JSON.

struct Movie: Codable {
    let title: String
    let releaseYear: Int
    let isClassic: Bool
}

I'll let you in on a professional tip: always use let for your model properties unless you specifically know you'll be mutating them locally. Data coming from an API should generally be treated as immutable snapshots.

Handling the Naming Gap with CodingKeys

You probably noticed a problem in my example above. The JSON uses release_year (snake_case), but in Swift, we use releaseYear (camelCase). If the names don't match exactly, JSONDecoder will throw an error and your app will crash or fail to load the data. I've spent way too many hours debugging this exact mismatch in my early career.

We fix this using a special enum called CodingKeys. This acts as a translation map, telling Swift: "When you see release_year in the JSON, put it into the releaseYear property in my struct."

struct Movie: Codable {
    let title: String
    let releaseYear: Int
    let isClassic: Bool

    enum CodingKeys: String, CodingKey {
        case title
        case releaseYear = "release_year"
        case isClassic = "is_classic"
    }
}

Putting the Decoder to Work

Now that we have our model, we use JSONDecoder to actually perform the assembly. Here is how I usually set this up in a real project:

let jsonString = """
{
    "title": "Inception",
    "release_year": 2010,
    "is_classic": true
}
"""

// Convert the string to Data, because JSONDecoder requires Data
if let jsonData = jsonString.data(using: .utf8) {
    do {
        let decoder = JSONDecoder()
        let movie = try decoder.decode(Movie.self, from: jsonData)
        print("Successfully decoded: \(movie.title) from \(movie.releaseYear)")
    } catch {
        print("Decoding failed: \(error)")
    }
}

Notice the Movie.self part. We aren't passing an instance of a movie; we're passing the type itself, telling the decoder, "I want you to try and create something that fits the Movie blueprint."




📋 Practical Task

Build a Recipe Data Model for a Cooking App

You've been given a JSON snippet representing a cooking recipe. Your task is to create a Swift data model that can decode this JSON, handling the discrepancy between the JSON's snake_case and Swift's camelCase.

The JSON data:

{
    "recipe_name": "Classic Margherita Pizza",
    "prep_time_minutes": 15,
    "is_vegetarian": true,
    "calories": 800
}

Requirements:

  • Create a struct named Recipe that conforms to Codable.
  • Use camelCase for the property names (e.g., recipeName instead of recipe_name).
  • Implement CodingKeys to map the JSON keys to your Swift properties.
  • Write the code to decode the JSON string into a Recipe object using JSONDecoder.
  • Print the recipeName of the decoded object to the console to verify it works.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.