Fetch Data From Nested JSON In API In Swift

Anjali Joshi
5 min readMar 9, 2024

--

This article contains simple demo on how to fetch data from nested JSON in API using URLSession in Swift programming language.

So lets begin by creating a Playground.

Open XCode. Select File -> New -> Playground. Select iOS -> Blank file. Name and save it to a desired location.

Steps to create a Playground in XCode
Blank Playground

In this demo, we will fetch the data from a dummy API. The URL endpoint that we will be using is https://jsonplaceholder.typicode.com/users.

So let’s begin by creating structs that conform to the Codable Protocol.

Codable protocol is a type alias for Encodable and Decodable protocols. Encodable protocol is used to convert data into external representation such as JSON whereas Decodable protocol is used to convert external representation data into the data that we need.

NOTE: Make sure all the names of the variables match with the keyword used in the JSON in the URL link. Also, match the data types according to the values used in the JSON data.

So let’s check the JSON carefully and create a struct User according to it.

struct User: Codable {
// The names of the variables should match with the keys used in the link. Also, the data types should match with the values of the URL link.
let id: Int
let name: String
let username: String
let email: String
let address: Address
let phone: String
let website: String
let company: Company
}

In the JSON data, the keys address and company contain a nested loop, hence we will be creating structs Address and Company respectively which will contain the desired keys within it.

struct Address: Codable {
// The names of the variables should match with the keys used in the link. Also, the data types should match with the values of the URL link.
let street: String
let suite: String
let city: String
let zipcode: String
let geo: Geo
}

struct Company: Codable {
// The names of the variables should match with the keys used in the link. Also, the data types should match with the values of the URL link.
let name: String
let catchPhrase: String
let bs: String
}

The geo key within the address key contains another nested loop. Hence we will be creating another struct named Geo for the keys within the geo key.

struct Geo: Codable {
// The names of the variables should match with the keys used in the link. Also, the data types should match with the values of the URL link.
let lat: String
let lng: String
}

Once the structs are created, we will create a request to call the API. For that, we will be using the URLRequest.

URLRequest creates a URL request with the given URL, cache policy, and timeout interval.

In the playground, add the following code:

let url = URL(string: "https://jsonplaceholder.typicode.com/users")!
var request = URLRequest(url: url)
request.httpMethod = "GET" // optional
request.setValue("application/json", forHTTPHeaderField: "Content-Type")

In the above code, since we are fetching the data from API, we are providing the httpMethod as GET.

If you need to create and send any data to API, at that time the httpMethod will be POST. By default, the httpMethod will be GET. Hence, the line request.httpMethod = “GET” is optional.

Now, we will be using dataTask of URLSession to retrieve the contents of the URL.

URLSession is an object that coordinates a group of related network data transfer tasks. The URLSession class and related classes provide an API by downloading and uploading data to endpoints indicated by URL.

‘shared’ is a shared singleton session object to fetch contents of URL to memory using few lines of code.

‘dataTask’ is used to retrieve contents of URL based on specified URL request object and calls a handler upon completion.

Add the following code:

let task = URLSession.shared.dataTask(with: request){ data, response, error in
if let error = error {
print("Error while fetching data:", error)
return
}

guard let data = data else {
return
}

do {
// Since the JSON in the URL starts with array([]), we will be using [User].self. If the JSON starts with curly braces ({}), use User.self
let users = try JSONDecoder().decode([User].self, from: data)
for user in users {
print("ID:", user.id)
print("Name:", user.name)
print("Username:", user.username)
print("Email:", user.email)
print("==== Address Details====")
print("Street:", user.address.street)
print("Suite:", user.address.suite)
print("City:", user.address.city)
print("Zipcode:", user.address.zipcode)
print("==== Geo ====")
print("Latitude:", user.address.geo.lat)
print("Longitude:", user.address.geo.lng)
print("==================")
print("Phone:", user.phone)
print("Website:", user.website)
print("==== Company ====")
print("Company Name:", user.company.name)
print("Catchphrase:", user.company.catchPhrase)
print("BS:", user.company.bs)
print("============")
}
} catch let jsonError {
print("Failed to decode json", jsonError)
}
}

NOTE: The JSON in the URL starts with an array i.e. [ ]. Hence we are passing the data type as an array of the struct i.e [User].self to the decode method of JSONDecoder. If the JSON starts with curly braces { }, then we will be passing the data type as Struct directly i.e. User.self.

Since the data fetched is in the JSON format, we will have to decode it. For that, we have used JSONDecoder in the above code.

JSONDecoder is used to decode instances of data type from JSON objects.

At last, add the following line of code.

task.resume()

‘resume()’ is important to start the data task as well as to start the tasks if they are suspended. The above code won’t run if this line of code is missed.

That’s it! Run the Playground. If everything goes well, you must see the data in the console of the Playground.

Output

--

--