How to decode JSON in Swift. All you need to know.

JSON is one of the most common data formats for transferring data between servers and devices. Parsing JSON in Swift is a common task to do because almost every app uses JSON to present data in one or the other way. Let's learn everything you need to know about it.

How to decode JSON in Swift.

  1. Fetch JSON data using a network request or open a local file.
  2. Make sure your model types conform to the Decodable protocol.
  3. Pass the data to the JSONDecoder instance using created Decodable models.

Let's dive in.

Decode JSON in Swift using Decodable protocol.

Let's take a look at how to decode JSON data in Swift using JSONDecoder. Here is the simplified 'user' response from  Github Rest API.

{
  "login": "octocat",
  "id": 1,
  "url": "https://api.github.com/users/octocat",
  "email": "octocat@github.com",
  "plan": {
    "name": "Medium",
    "space": 400,
    "private_repos": 20,
    "collaborators": 0
  }
}
GET /user from Github REST API

We can decode that data by creating the following structure, that conforms to the Decodable protocol:

struct User: Decodable {
    let login: String
    let id: Int
    let url: String
    let email: String
    let plan: UserPlan
}

struct UserPlan: Decodable {
    let name: String
    let space: Int
    let private_repos: Int
    let collaborators: Int
}
Decoding JSON using Decodable protocol

We defined two structures that conform to the Decodable protocol and used a custom-defined  Decodable type UserPlan as a plan property in the 'User' structure. This is possible because every type that conforms to the Decodable protocol will be automatically converted.

ApiScout - REST API Client for macOS

Build, test, and describe APIs. Fast.

Download Now

Now we can use the JSONDecoder instance to map user JSON data into our freshly created model:

let user = try! JSONDecoder().decode(User.self, from: data)
Decoding JSON Data in Swift using JSONDecoder

That's it. We decoded JSON data using JSONDecoder into our model.

Custom property names

In the sample above we made all the properties match the names of keys from JSON. If you like to define different property names, you can create mapping by defining a custom CodingKeys enum inside of the desired model structure.

In the previous example, we could name private_repos property as privateRepos:

struct UserPlan: Decodable {
    let name: String
    let space: Int
    let privateRepos: Int
    let collaborators: Int
    
    enum CodingKeys: String, CodingKey {
        case name, space, collaborators
        // Map the JSON key "private_repos" to the Swift property name "privateRepos"
        case privateRepos = "private_repos"
    }
}
Custom property name mapping using CodingKeys enum

For this special case, you could also avoid defining the CodingKeys and use the .convertFromSnakeCase strategy of JSONDecoder instead:

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let user = try! decoder.decode(User.self, from: data)
Using decoding strategy for conversion between camel and snake cases

Edge cases

  1. It is not necessary to define each property
  2. Use optional if you are not sure whether a JSON key is mandatory or not.

Decode JSON Arrays in Swift.

Decoding a JSON array is just as simple as decoding a single JSON object.

Let's consider we have an array of users like this:  

[{
  "login": "octocat",
  "id": 1,
  "url": "https://api.github.com/users/octocat",
  "email": "octocat@github.com",
  "plan": {
    "name": "Medium",
    "space": 400,
    "private_repos": 20,
    "collaborators": 0
  }
},
{
  "login": "tortilla",
  "id": 2,
  "url": "https://api.github.com/users/tortilla",
  "email": "tortilla@github.com",
  "plan": {
    "name": "Medium",
    "space": 213,
    "private_repos": 3,
    "collaborators": 12
  }
}]

Swift Decodable protocol makes decoding JSON data in Swift easy.