Search code examples
swiftjsondecoder

Decode JSON response from API


I get some JSON objects from my api that look like this:

{
    "from": "1970-01-01",
    "until": null,
    "employeeId": "13",
    "project": {
        "id": "05c6adce-20cd-4ca3-9eff-8fd430f63a20",
        "version": 0,
        "name": "AGFA",
        "code": "AGFA",
        "start": "2016-01-01",
        "end": "2016-12-31",
        "alternativeCodes": []
    }
},

And I want to use the different parts of it in my program. I did some research and came up with this solution:

import SwiftUI
import CryptoKit

struct Project: Decodable {
    let id: String
    let version: Int
    let name: String
    let code: String
    let start: Date
    let end: Date
    let alternativeCode: [String]
}

struct AssignedProject: Decodable{
    let from: Date
    let until: Date
    let emloyeeId: Int
    let project: Project
}



struct FetchWebsiteView: View {
@Binding var apiKey : String
@State var assignedProjects = [AssignedProject]()
var body: some View {     
    VStack{
        
    }.onAppear{
        Task {
           var x = await doHTTPProjectsCall(token: apiKey)                                
        }
    }
}

func doHTTPProjectsCall(token:String) async -> Array<String> {
    let url = "http://localhost:8160/api/v1/project/assignments/13"
    guard let reqUrl = URL(string: url) else {
        print("Invalid URL")
        return(Array())
    }
    var req = URLRequest(url: reqUrl)
    req.httpMethod = "GET"
    req.setValue("CC0001", forHTTPHeaderField: "CC-Tenant")
    req.setValue("BE", forHTTPHeaderField: "CC-Product")
    
    let task = URLSession.shared.dataTask(with: req) { data, response, error in
        if let data = data {
            let decoder = JSONDecoder()
            decoder.dateDecodingStrategy = .iso8601

            print("Program goes fine till here")

            if let decodedResponse = try?
                decoder.decode([AssignedProject].self, from: data) {

                print("Not doing this too")

                DispatchQueue.main.async {
                    self.assignedProjects = decodedResponse
                    print("Not doing this")
                }
                return
                }
        } else if let error = error {
            print("HTTP Request Failed \(error)") // not printing any errors
        }
        if let response = response as? HTTPURLResponse {
                print("Response HTTP Status code: \(response.statusCode)") // but doing this fine and returning with status code 200 OK
            }
    }
    task.resume()
    
    
    return ["Internship", "Project2", "Test"]
}
}

Since it's not printing any errors and answering with status code 200 OK, i assume the request is fine but I have a problem decoding the JSON object. Thanks in advance


Solution

  • There is a lot going on with the structs you try to decode to. You got several typos in here. E.g. alternativeCode instead of alternativeCodes...

    Next there are several type mismatches here. For example employeeId is a String and not an Int.

    Next the dates need a custom dateformatter to be decoded succesfully.

    struct Project: Decodable {
        let id: String
        let version: Int
        let name: String
        let code: String
        let start: Date
        let end: Date
        let alternativeCodes: [String]
    }
    
    struct AssignedProject: Decodable{
        let from: Date
        let until: Date?
        let employeeId: String
        let project: Project
    }
    
    
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .formatted(formatter)
    let result = try decoder.decode([AssignedProject].self, from: data)