DEV Community

arenasbob2024-cell
arenasbob2024-cell

Posted on • Originally published at viadreams.cc

JSON to Swift Struct: Complete Guide with Codable and JSONDecoder

Convert JSON to Swift structs with the Codable protocol. Here's everything iOS/macOS developers need.

Basic Codable Struct

import Foundation

struct User: Codable {
    let id: Int
    let name: String
    let email: String
    let active: Bool
}

// Decode
let json = """{"id":1,"name":"Alice","email":"alice@example.com","active":true}"""
let user = try JSONDecoder().decode(User.self, from: json.data(using: .utf8)!)

// Encode
let encoded = try JSONEncoder().encode(user)
let jsonString = String(data: encoded, encoding: .utf8)!
Enter fullscreen mode Exit fullscreen mode

CodingKeys — Snake Case to Camel Case

struct ApiResponse: Codable {
    let userId: Int
    let firstName: String
    let avatarUrl: String

    enum CodingKeys: String, CodingKey {
        case userId = "user_id"
        case firstName = "first_name"
        case avatarUrl = "avatar_url"
    }
}

// Or use keyDecodingStrategy (simpler for all fields)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let response = try decoder.decode(ApiResponse.self, from: data)
Enter fullscreen mode Exit fullscreen mode

Optional Properties

struct User: Codable {
    let id: Int
    let name: String
    let bio: String?          // nil if absent or null
    let avatarUrl: String?    // nil if absent or null

    enum CodingKeys: String, CodingKey {
        case id, name, bio
        case avatarUrl = "avatar_url"
    }
}

// Default values with custom init
struct Config: Codable {
    let timeout: Int
    let retries: Int

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        timeout = try container.decodeIfPresent(Int.self, forKey: .timeout) ?? 30
        retries = try container.decodeIfPresent(Int.self, forKey: .retries) ?? 3
    }
}
Enter fullscreen mode Exit fullscreen mode

Nested Structs and Arrays

struct Order: Codable {
    let orderId: String
    let customer: Customer
    let items: [OrderItem]
    let tags: [String]

    enum CodingKeys: String, CodingKey {
        case orderId = "order_id"
        case customer, items, tags
    }
}

// Decode array
let orders = try JSONDecoder().decode([Order].self, from: data)
Enter fullscreen mode Exit fullscreen mode

Enums with RawRepresentable

enum Status: String, Codable {
    case active = "active"
    case inactive = "inactive"
    case pending = "pending"
}

struct User: Codable {
    let id: Int
    let name: String
    let status: Status  // decodes "active" → .active
}
Enter fullscreen mode Exit fullscreen mode

Date Handling

let decoder = JSONDecoder()

// ISO 8601 strings: "2024-01-15T10:30:00Z"
decoder.dateDecodingStrategy = .iso8601

// Unix timestamps: 1705312200
decoder.dateDecodingStrategy = .secondsSince1970

// Custom format
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
decoder.dateDecodingStrategy = .formatted(formatter)

struct Event: Codable {
    let id: Int
    let name: String
    let startDate: Date
}
Enter fullscreen mode Exit fullscreen mode

async/await with URLSession

struct APIClient {
    let decoder: JSONDecoder = {
        let d = JSONDecoder()
        d.keyDecodingStrategy = .convertFromSnakeCase
        d.dateDecodingStrategy = .iso8601
        return d
    }()

    func fetchUser(id: Int) async throws -> User {
        let url = URL(string: "https://api.example.com/users/\(id)")!
        let (data, response) = try await URLSession.shared.data(from: url)

        guard let http = response as? HTTPURLResponse, http.statusCode == 200 else {
            throw URLError(.badServerResponse)
        }

        return try decoder.decode(User.self, from: data)
    }
}
Enter fullscreen mode Exit fullscreen mode

Quick Tool

For automatic Swift struct generation from JSON, use DevToolBox JSON to Swift converter — paste JSON, get Swift structs with Codable instantly.


Generate Swift structs from JSON instantly with DevToolBox's free JSON to Swift tool.

Top comments (0)