How to parse JSON in iOS using Swift

Today, I’m going to show you how to parse JSON in your iOS app without using any 3rd party library.

There are are two ways to parse a JSON natively in iOS:

  • JSONSerialization: This is the old fashion way to parse JSON. It’s recommended only when you want to parse one or two JSON objects.
  • JSONDecoder: This method is available only in Swift 4 and later. You create your model and after parsing the JSON you’ll get an object with all the fields already filled.

In this tutorial, I’ll cover 3 cases that may you face when you’re trying to parse JSON:

  • Simple JSON: Just a simple JSON without any complex structure
  • Array JSON: The JSON structure begins with an array and without a key
  • Nested JSON: Includes nested objects

Simple JSON

A simple JSON doesn’t have any complex structure, like arrays, nested objects e.t.c, and it looks like that:

{ "id": "1", "employee_name": "Jack Full", "employee_salary": "300800", "employee_age": "61" }
Code language: Swift (swift)

• JSONSerialization Method

To parse JSON with the JSONSerialization method, you take the data after the HTTP request, and then you parse JSON like that:

if let json = try! JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] { // ID let id = json["id"] as? String ?? "N/A" print("ID: \(id)") // Employee Name let employeeName = json["employee_name"] as? String ?? "N/A" print("Employee Name: \(employeeName)") // Employee Salary let employeeSalary = json["employee_salary"] as? String ?? "N/A" print("Employee Salary: \(employeeSalary)") // Employee Age let employeeAge = json["employee_age"] as? String ?? "N/A" print("Employee Age: \(employeeAge)") }
Code language: Swift (swift)

Tip: When there are curly brackets { } with JSON objects inside. We’re parsing them using Dictionary –> ‘[String: Any]’

• JSONDecoder Method

In JSONDecoder method, we create a model that conforms the Codable protocol. In this example, we call it SimpleJSONModel:

class SimpleJSONModel: Codable { let employee_id: String let employee_name: String let employee_salary: String let employee_age: String enum CodingKeys: String, CodingKey { case employee_id = "id" case employee_name case employee_salary case employee_age } }
Code language: Swift (swift)

Tip: If you don’t want to create the model manually, you can use the Quicktype.io to generate it.

As you see, every declared value in the model has the same name with the JSON keys, except the ‘id‘ (It’s called ‘employee_id‘ in our model).

To be able to get the ‘id‘ from the JSON using the ‘employee_id‘ in our model, we use a nested enumeration named CodingKeys that conforms to the CodingKey protocol, and we rename it.

Then using the JSONDecoder class and the model we created before, we parse JSON using the data from the HTTP request:

let jsondecode = try! JSONDecoder().decode(SimpleJSONModel.self, from: data) // ID let id = jsondecode.employee_id print("ID: \(id)") // Employee Name let employeeName = jsondecode.employee_name print("Employee Name: \(employeeName)") // Employee Salary let employeeSalary = jsondecode.employee_salary print("Employee Salary: \(employeeSalary)") // Employee Age let employeeAge = jsondecode.employee_age print("Employee Age: \(employeeAge)")
Code language: Swift (swift)

If you don’t know how to make HTTP requests, I recently wrote how to do it using Alamofire and URLSession

Tip: When there are square brackets [ ] with JSON objects inside. We’re parsing them using Array –> ‘[Any]’

Array JSON

Sometimes, you might see a JSON start with an array and without having a key:

[ { "id": "1", "employee_name": "Tiger Nixon", "employee_salary": "320800", "employee_age": "61" }, { "id": "2", "employee_name": "Garrett Winters", "employee_salary": "170750", "employee_age": "63" }, // ... ]
Code language: Swift (swift)

• JSONSerialization Method

With the JSONSerialization method to parse this type of JSON, you need to convert the JSON array as [Any], and then get the JSON objects inside the for loop:

if let json = try! JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [Any] { for item in json { if let object = item as? [String: Any] { // ID let id = object["id"] as? String ?? "N/A" print("ID: \(id)") // Employee Name let employeeName = object["employee_name"] as? String ?? "N/A" print("Employee Name: \(employeeName)") // Employee Salary let employeeSalary = object["employee_salary"] as? String ?? "N/A" print("Employee Salary: \(employeeSalary)") // Employee Age let employeeAge = object["employee_age"] as? String ?? "N/A" print("Employee Age: \(employeeAge)") // Save data using your Model } } // Reload data of TableView/CollectionView }
Code language: Swift (swift)

• JSONDecoder Method

With the JSONDecoder method, we create a model that conforms the Codable protocol for each item of the JSON array. In this example, we call it ArrayJSONModel:

struct ArrayJSONModel: Codable { let employee_id: String let employee_name: String let employee_salary: String let employee_age: String enum CodingKeys: String, CodingKey { case employee_id = "id" case employee_name case employee_salary case employee_age } }
Code language: Swift (swift)

Then we parse JSON using this model inside of an array (e.g. [ArrayJSONModel]):

let json = try! JSONDecoder().decode([ArrayJSONModel].self, from: data) for item in json { // ID let id = item.employee_id print("ID: \(id)") // Employee Name let employeeName = item.employee_name print("Employee Name: \(employeeName)") // Employee Salary let employeeSalary = item.employee_salary print("Employee Salary: \(employeeSalary)") // Employee Age let employeeAge = item.employee_age print("Employee Age: \(employeeAge)") // Save data using your Model } // Reload data of TableView/CollectionView
Code language: Swift (swift)

Nested JSON

When a JSON object is inside another JSON object, it’s called ‘nested’, and will look like the following JSON structure:

{ "data": [ { "id": "1", "employee": { "name": "Tiger Nixon", "salary": { "usd": 320800, "eur": 273545 }, "age": "61" } }, { "id": "2", "employee": { "name": "Garrett Winters", "salary": { "usd": 170750, "eur": 145598 }, "age": "63" } }, // ... ] }
Code language: Swift (swift)

• JSONSerialization Method

To parse this complex JSON nesting of objects and array using the JSONSerialization method, you just get the data after the HTTP request, and then:

var employeeName: String! var employeeSalaryUSD: Int! var employeeSalaryEUR: Int! var employeeAge: String! let json = try! JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] if let data = json?["data"] as? [Any] { for item in data { if let object = item as? [String: Any] { // ID let id = object["id"] as? String ?? "N/A" print("ID: \(id)") if let employee = object["employee"] as? [String: Any] { // Employee Name let employeeName = employee["name"] as? String ?? "N/A" self.employeeName = employeeName print("Employee Name: \(employeeName)") // Salary if let salary = employee["salary"] as? [String: Any] { // Employee Salary in USD if let employeeSalaryUSD = salary["usd"] as? Int { self.employeeSalaryUSD = employeeSalaryUSD print("Employee Salary in USD: \(employeeSalaryUSD)") } // Employee Salary in EUR if let employeeSalaryEUR = salary["eur"] as? Int { self.employeeSalaryEUR = employeeSalaryEUR print("Employee Salary in EUR: \(employeeSalaryEUR)") } } // Employee Age let employeeAge = employee["age"] as? String ?? "N/A" self.employeeAge = employeeAge print("Employee Age: \(employeeAge)") } // Save data using your Model } } // Reload data of TableView/CollectionView }
Code language: Swift (swift)

• JSONDecoder Method

With the JSONDecoder method, first, we create a model, in this example called NestedJSONModel:

struct NestedJSONModel: Codable { let data: [Datum] enum CodingKeys: String, CodingKey { case data } } // MARK: - Datum struct Datum: Codable { let employee_id: String let employee: Employee enum CodingKeys: String, CodingKey { case employee_id = "id" case employee } } // MARK: - Employee struct Employee: Codable { let name: String let salary: Salary let age: String enum CodingKeys: String, CodingKey { case name case salary case age } } // MARK: - Salary struct Salary: Codable { let usd: Int let eur: Int enum CodingKeys: String, CodingKey { case usd case eur } }
Code language: Swift (swift)

Then with this model, we get the nested JSON objects inside the for loop of the ‘data‘ array:

let json = try! JSONDecoder().decode(NestedJSONModel.self, from: data) let dataArray = json.data for item in dataArray { // ID let id = item.employee_id print("ID: \(id)") // Employee Name let employeeName = item.employee.name print("Employee Name: \(employeeName)") // Employee Salary in USD let employeeSalaryUSD = item.employee.salary.usd print("Employee Salaray USD: \(employeeSalaryUSD)") // Employee Salary in EUR let employeeSalaryEUR = item.employee.salary.eur print("Employee Salaray EUR: \(employeeSalaryEUR)") // Employee Age let employeeAge = item.employee.age print("Employee Age: \(employeeAge)") // Save data using your Model } // Reload data of TableView/CollectionView
Code language: Swift (swift)
You can find the final project here

If you have any questionsplease feel free to leave a comment below

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

Get once a week my latest tutorials right in your inbox

Check your inbox to confirm your email