swiftuikitalamofirejsonparser

How do I decode json Dictionary into a struct that I want and use that data to populate my Table View


I have a data model which is a struct and I have an API which has JSON dictionary. I need to populate my table view cells with the values in the dictionary. I have already created an array containing the key values to pass it to one of the labels in my viewcontroller. I have a text field and a label and I want the data from the API to be displayed corresponding to the array elements in my array containing keys.

This is My view controller [Edited] ;

import UIKit

class FirstViewController: UIViewController {
    
    
    @IBOutlet weak var DataTable: UITableView!
    
    var UserArr = ["ID", "UID", "Password", "First Name", "Last Name", "Username", "Email", "Avatar", "Gender", "Phone Number", "Social Insurance Number", "Date Of Birth", "Employment", "Address", "Zip Code", "State", "Country", "Coordinates", "CC Number", "Subscription"]
    
    var userDataFromApi = [UserData]()
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        NetworkManager.sharedInstance.fetchData{
            apiData in
            self.userDataFromApi = apiData
            DispatchQueue.main.async { [self] in
                DataTable.reloadData()
            }
        }
        
        DataTable.dataSource = self
        DataTable.delegate = self
                       
        
    }
            
}

extension FirstViewController : UITableViewDelegate,UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return userDataFromApi.count
    }
   
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = DataTable.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! DataTableViewCell
        
        let rowdata = userDataFromApi[indexPath.row]
        cell.txtLabel.text = UserArr[indexPath.row]
        cell.txtField.text = rowdata.first_name
        return cell
    }
    
    
}

My data Model

import Foundation

struct UserData : Codable {        
    let id : Int
    let uid : String
    let password : String
    let first_name : String
    let last_name : String
    let username : String
    let email : String
    let avatar : String
    let gender : String
    let phone_number : String
    let social_insurance_number : String
    let date_of_birth : String
    let employment : Employment
    
    
    struct Employment : Codable {
        let title : String
        let key_skill: String
    }
    
    
    let address : Address
    struct Address : Codable {
        let city : String
        let street_name : String
        let street_address : String
        let zip_code : String
        let state : String
        let country : String
        let coordinates : Coordinates
        struct Coordinates : Codable {
            let lat : Double
            let lng : Double
        }
    }
    
    
    let credit_card : Credit_card
    struct Credit_card : Codable {
        let cc_number : String
    }
    
    let subscription : Subscription?
    struct Subscription : Codable {
        let plan : String
        let status : String
        let payment_method : String
        let term : String
    }
            
}

Where I make API requests

import Foundation
import Alamofire

class NetworkManager {
    static let sharedInstance = NetworkManager()
    private init() {
        
    }
    
    func fetchData(handler: @escaping (_ apiData :[UserData]) -> (Void)){
        guard let url = URL(string: "https://random-data-api.com/api/v2/users")
        else {
            return
            
        }
        AF.request(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil, interceptor: nil) .response  { resp in
            switch resp.result {
            case  .success(let data) :
                do {
                    let json = try JSONDecoder().decode([UserData].self, from: data!)
                    print("Data is : \(json)")
                    print(type(of: json))
                    handler(json)
                }
                catch{
                    print(error)
                }
            case .failure(let error) :
                print(error.localizedDescription)
            }
                                                
        }
    }
                
}

At first I tried to parse it as array but it doesn't load anything. Please feel free to suggest improvements because I am a beginner in learning Swift.


Solution

  • At first I tried to parse it as array but it doesn't load anything. Please feel free to suggest improvements because I am a beginner in learning Swift.

    It is because from your api you're getting dictionary and you're trying to store it in array.

    you need to change you're api call function slightly.

    func fetchData(handler: @escaping (_ apiData :UserData) -> (Void)){
            guard let url = URL(string: "https://random-data-api.com/api/v2/users")
            else {
                return
                
            }
            AF.request(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil, interceptor: nil) .response  { resp in
                switch resp.result {
                case  .success(let data) :
                    do {
                        let json = try JSONDecoder().decode(UserData.self, from: data!)
                        print("Data is : \(json)")
                        print(type(of: json))
                        handler(json)
                    }
                    catch{
                        print(error)
                    }
                case .failure(let error) :
                    print(error.localizedDescription)
                }
                
            }
        }
    
    NetworkManager.sharedInstance.fetchData{
        apiData in
        print("api data - ",apiData)
        // you can save your data in array accordingly
    }