Fetch Data From Nested JSON In API

In this article, we will learn to fetch data from nested JSON in API using URLSession in Swift programming language.

Also, please check out my article, Fetch Data From API Using URLSession, to start with a simpler example.

Prerequisites

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

    Project
  • 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. You can use Postman to check if the endpoint works or not.
  • 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, line number 3(as per the above code) 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 the contents of the URL to memory using a 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
        }
    }
  • In the above code, 'data' contains the contents of the URL in the JSON format. 'response' will give you the response code, and 'error' is used to display errors that occurred, if any.
  • Since the data fetched is in the JSON format, we will have to decode it. For that, we will be using JSONDecoder.
  • JSONDecoder is used to decode instances of data type from JSON objects.
  • Add the below code after line number 9 (line as per above code).
    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 pass the data type as Struct directly, i.e., User.self.
  • 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! Now, run to the Playground. If everything goes well, you must see the data in the console of the Playground.


Similar Articles