Home > Software design >  Decode JSON response from API
Decode JSON response from API

Time:07-16

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

CodePudding user response:

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)

CodePudding user response:

First of all, make your structs is Codable and make String the variables (start, end, from, until) you define as Date and use optional (?) for variables that may be empty. Also small mistake change alternativeCode to alternativeCodes :)

struct Project: Codable {
   let id: String
   let version: Int?
   let name: String?
   let code: String?
   let start: String?
   let end: String?
   let alternativeCodes: [String]?
}

struct AssignedProject: Codable {
   let from: String?
   let until: String?
   let emloyeeId: Int
   let project: Project?
}
  • Related