iPhone
iOS
JSON
parsing
tutorial

iPhone/iOS JSON parsing tutorial

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

On iOS, JSON parsing usually means two tasks: fetching JSON from a server and decoding it into Swift types safely. Modern Swift code uses Codable for most of this work because it removes a large amount of manual dictionary casting. The important part is not only decoding successfully, but designing models and error handling that make malformed or changing payloads manageable.

Define Codable Models That Match the Payload

Suppose an API returns a user record like this.

json
1{
2  "id": 1,
3  "name": "Ada",
4  "email": "[email protected]"
5}

A matching Swift model is straightforward.

swift
1import Foundation
2
3struct User: Codable {
4    let id: Int
5    let name: String
6    let email: String
7}

When the JSON keys line up with the property names, JSONDecoder can decode the data with very little code.

Decode with JSONDecoder

The core parsing step looks like this.

swift
1import Foundation
2
3let json = """
4{
5  "id": 1,
6  "name": "Ada",
7  "email": "[email protected]"
8}
9""".data(using: .utf8)!
10
11let decoder = JSONDecoder()
12let user = try decoder.decode(User.self, from: json)
13print(user.name)

This is already enough for many local examples, tests, and small parsing tasks.

Parse Network JSON with URLSession

In real iOS code, the JSON usually comes from an API call.

swift
1import Foundation
2
3func fetchUser() {
4    let url = URL(string: "https://example.com/user.json")!
5
6    URLSession.shared.dataTask(with: url) { data, response, error in
7        guard let data = data, error == nil else {
8            print("network error:", error?.localizedDescription ?? "unknown")
9            return
10        }
11
12        do {
13            let user = try JSONDecoder().decode(User.self, from: data)
14            print("decoded user:", user)
15        } catch {
16            print("decode error:", error)
17        }
18    }.resume()
19}

The important separation is this: networking can fail for transport reasons, and parsing can fail because the JSON shape does not match the model. Keep those failures distinct.

Handle Key Mismatches Explicitly

Sometimes the JSON keys do not match your Swift property names. CodingKeys lets you map them cleanly.

swift
1struct User: Codable {
2    let id: Int
3    let fullName: String
4
5    enum CodingKeys: String, CodingKey {
6        case id
7        case fullName = "name"
8    }
9}

This is better than renaming your Swift properties to mirror every backend naming quirk.

Use Optional Properties for Truly Optional Data

APIs often omit fields. If a field is genuinely optional in the payload, reflect that in the model.

swift
1struct User: Codable {
2    let id: Int
3    let name: String
4    let phone: String?
5}

This is safer than making everything optional by default. Optionality should communicate actual uncertainty in the data contract, not just fear of decoding errors.

Debug the Payload Before Blaming the Decoder

Many JSON parsing problems are data-shape problems. A top-level array decoded as an object, a string where an integer was expected, or a nested key path that the model ignored can all cause failure.

When decoding fails, print the raw response or inspect a sample payload before rewriting the model blindly. The decoder error is useful, but only if you compare it with the real JSON shape.

Common Pitfalls

  • Parsing into the wrong top-level type, such as decoding an object as if it were an array.
  • Making every property optional instead of modeling the real contract clearly.
  • Mixing transport errors with decoding errors and losing the real cause.
  • Expecting key names to map automatically when the server uses different naming.
  • Casting JSON through untyped dictionaries when Codable would be simpler and safer.

Summary

  • On iOS, modern JSON parsing is usually Codable plus JSONDecoder.
  • Define Swift models that match the payload shape.
  • Use URLSession to fetch network JSON and decode it separately from transport handling.
  • Map mismatched keys with CodingKeys.
  • Treat optional properties and decoding errors deliberately rather than guessing.

Course illustration
Course illustration

All Rights Reserved.