Search code examples
iosjsonswift

Parsing the JSON in tableview using Swift


I am new in parsing JSON. I made a single view application. I got JSON from URL using this function:

func parseData(){
        //created URL
        guard let requestURL = URL(string: "https://machla.bh/api-category2") else {return }
        
        //creating URLRequest
        var request = URLRequest(url: requestURL)
        
        //setting the method to post
        request.httpMethod = "POST"
        
        //creating the post parameter by concatenating the keys and values from text field
        var postParameters = ""
        
        postParameters += "key=LpfyirxoNOfP8wPns4nZqTw6DQ4wY A2q6yvpKsof6gkYDTykVXSEonTO2VB HE2zRdqrvsyoyMVyRagWtKAtVuOuNs c7QW5KrgbXS8SqPZ7sIDlPEvhBWyo5 NoObAcor3GlO87nRSaFdxhKDRTiBkK 3pFsTQyffzuBdIBiM8zFra6Yh8NbbC QQaratgFFE2hzLouNEIHq88xaSqum1 C0z7g325i3hixT5oLSo5tvhpvvdTJO WohfqGSakeGz7hsAU"
        
        postParameters += "&path=59"
        
        postParameters += "&language_id=1"
        
        //adding the parameters to request body
        request.httpBody = postParameters.data(using: .utf8)
        
        //creating a task to send the post request
        let session = URLSession.shared
        
        let task = session.dataTask(with: request) { data, response, error in
            
            guard error == nil else {
                print("error is \(error!.localizedDescription)")
                return
            }
            guard let data = data else {
                print("No data was returned by the request!")
                return
            }
            
            
            // print data from request
            let str = String(data: data, encoding: .utf8)!
              print(str)
            for eachFetechedCountry in str
            {
                let eachCountry=eachFetechedCountry as! [String:Any]
                let category = eachCountry["categories"] as! String
                let product=eachCountry["products"] as! String
                self.fetchcountry.append(Country(categories: category, products: product))
                
            }
            self.countryTableView.reloadData()
          
        }
        
        //executing the task
        task.resume()
        
  }

I am trying to read categories and products from JSON using following statement in the above function. These statements are not working. How to read categories and products from JSON?

 for eachFetechedCountry in str
                {
                    let eachCountry=eachFetechedCountry as! [String:Any]
                    let category = eachCountry["categories"] as! String
                    let product=eachCountry["products"] as! String
                    self.fetchcountry.append(Country(categories: category, products: product))
                    
                }

For populating categories and product into table view I created a class named Country:

class Country{

    var product:String
    var category:String
    
    init(categories :String, products:String)
    {
        self.category=categories
        self.product=products
    }
    
}

For populating categories and product into table view I coded:

func tableView(_ tableViewr: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = countryTableView.dequeueReusableCell(withIdentifier: "cell")
        cell?.textLabel?.text=fetchcountry[indexPath.row].category
        cell?.detailTextLabel?.text=fetchcountry[indexPath.row].product
        return cell!
        
    }

How to populate categories and product into table view?

From this link you can download sample project for correction?https://drive.google.com/file/d/0B5pNDpbvZ8SnY3RicXpGN1FYbXc/view?usp=sharing


Solution

  • You should use feature of Swift 4 - Decodable protocol.

        let task = session.dataTask(with: request) { data, response, error in
    
           guard error == nil else {
              print("error is \(error!.localizedDescription)")
              return
           }
    
           guard let data = data else {
              print("No data was returned by the request!")
              return
           }
    
           do {
              let country = try JSONDecoder().decode(Country.self, from: data)
    
              // do what you want here with Country array
              // ...
    
           } catch let error {
              // catch error and handled it here
           }
    
           DispatchQueue.main.async {
              self.countryTableView.reloadData()
           }
       }
    
       //executing the task
       task.resume()
    

    Always update tableview in Main thread!!!

    And use those structs:

    struct Country: Decodable{
        var categories: [Category]
    }  
    
    struct Category: Decodable {
        var name: String
        var products: [Product]
    }
    
    struct Product: Decodable {
        var name: String
    }