Last updated on: May 27, 2023
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
Contents
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 questions, please feel free to leave a comment below