salazar44
salazar44

Reputation: 142

Having trouble with my API Request. Curl Method with 2 headers

I would like some assistance trying to find out why I can't process this curl URLRequest in Swift. I believe my issue is how I am adding my headers but I can't figure this out. I've tried multiple ways without success. All the examples I am finding here don't seem to work for this situation.

When I get to the JSONDecoder I think it's decoding something, but not what I am expecting and the debugger doesn't get to the catch error.

Any assistance would be greatly appreciated!

import Foundation
import SwiftUI

class Network: ObservableObject {
    @Published var Loan: [LoanSelected] = []
            
    func getLoan() {
        guard let url = URL(string: "https://absws.com/TmoAPI/v1/LSS.svc/GetLoan/1001")
        else
        {
            return
        }
        
        var urlRequest = URLRequest(url: url)
        let headers = [
            "Token": "VIC",
            "Database": "World"
        ]
        
        //urlRequest.httpMethod = "GET"
        //urlRequest.addValue("ABS", forHTTPHeaderField: "Token")
        //urlRequest.addValue("World Mortgage Company", forHTTPHeaderField: "Database")
        //urlRequest.httpBody = payload
        urlRequest.httpMethod = "GET"
        urlRequest.allHTTPHeaderFields = headers

        
        let dataTask = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
            if let error = error {
                print("Request error: ", error)
                return
            }
            
            guard let response = response as? HTTPURLResponse else { return }
            
            if response.statusCode == 200 {
                guard let data = data else { return }
                DispatchQueue.main.async {
                    do {
                        let decodedUsers = try JSONDecoder().decode([LoanSelected].self, from: data)
                        self.Loan = decodedUsers
                    } catch let error {
                        print("Error decoding: ", error)
                    }
                }
            }
        }
        
        dataTask.resume()
    }
}

Upvotes: 0

Views: 130

Answers (1)

You are not getting an array [LoanSelected] from the server with the url you show.

Try this approach, using model struts that match the json data you are getting from the API.

Here is my test code, works well for me.

Use https://app.quicktype.io/ to generate the correct model structs for you.

struct ContentView: View {
    @StateObject var network = Network()
    
    var body: some View {
        ScrollView {
            Text("Loan")
                .font(.title)
                .bold()
            
            VStack(alignment: .leading) {
                HStack(alignment:.top) {
                    Text("\(network.loan?.account ?? "no account")")
                    VStack(alignment: .leading) {
                        Text(network.loan?.bankName ?? "no bank").bold()
                    }
                }
                .frame(width: 300, alignment: .leading)
                .padding()
                .cornerRadius(20)
            }
        }
        .padding(.vertical)
        .onAppear {
            network.getLoan()
        }
    }
}

class Network: ObservableObject {
    @Published var loan: Loan?  // <-- here
    
    func getLoan() {
        guard let url = URL(string: "https://absws.com/TmoAPI/v1/LSS.svc/GetLoan/1001"),
              let payload = "".data(using: .utf8) else {
            return
        }
        
        var urlRequest = URLRequest(url: url)
        urlRequest.httpMethod = "GET"
        urlRequest.addValue("ABS", forHTTPHeaderField: "Token")
        urlRequest.addValue("World Mortgage Company", forHTTPHeaderField: "Database")
        urlRequest.httpBody = payload
        
        let dataTask = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
            if let error = error {
                print("Request error: ", error)
                return
            }

            guard let response = response as? HTTPURLResponse else { return }
            
            if response.statusCode == 200 {
                guard let data = data else { return }
                DispatchQueue.main.async {
                    do {
                        let decoded = try JSONDecoder().decode(ApiData.self, from: data) // <-- here
                        self.loan = decoded.data
                    } catch let error {
                        print("Error decoding: ", error)
                    }
                }
            }
        }
        dataTask.resume()
    }
}

struct ApiData: Codable {
    let data: Loan
    let errorMessage: String
    let errorNumber, status: Int

    enum CodingKeys: String, CodingKey {
        case data = "Data"
        case errorMessage = "ErrorMessage"
        case errorNumber = "ErrorNumber"
        case status = "Status"
    }
}

struct Loan: Codable {
    let type, account, accountNumber, accountType: String
    let applyAs, bankAddress, bankName, borrowerRecID: String
    let byLastName: String?
    let cdfiReporting: String
    let coBorrowers: [String]
    let customFields: [CustomField]
    let debitAmount, debitDueDay, emailAddress, emailFormat: String
    let frequency, individualID, individualName, isTemplate: String
    let losLoanRecID, nextDebitDate, notes: String
    let primaryBorrower: PrimaryBorrower
    let primaryProperty: String?
    let recID, routingNumber, serviceStatus, sortName: String
    let stopDate: String
    let sysTimeStamp: String?
    let terms: [String: String?]
    let useDebitAmount, wpcPin, wpcPublish: String

    enum CodingKeys: String, CodingKey {
        case type = "__type"
        case account = "Account"
        case accountNumber = "AccountNumber"
        case accountType = "AccountType"
        case applyAs = "ApplyAs"
        case bankAddress = "BankAddress"
        case bankName = "BankName"
        case borrowerRecID = "BorrowerRecID"
        case byLastName = "ByLastName"
        case cdfiReporting = "CDFIReporting"
        case coBorrowers = "CoBorrowers"
        case customFields = "CustomFields"
        case debitAmount = "DebitAmount"
        case debitDueDay = "DebitDueDay"
        case emailAddress = "EmailAddress"
        case emailFormat = "EmailFormat"
        case frequency = "Frequency"
        case individualID = "IndividualId"
        case individualName = "IndividualName"
        case isTemplate = "IsTemplate"
        case losLoanRecID = "LOSLoanRecID"
        case nextDebitDate = "NextDebitDate"
        case notes = "Notes"
        case primaryBorrower = "PrimaryBorrower"
        case primaryProperty = "PrimaryProperty"
        case recID = "RecID"
        case routingNumber = "RoutingNumber"
        case serviceStatus = "ServiceStatus"
        case sortName = "SortName"
        case stopDate = "StopDate"
        case sysTimeStamp = "SysTimeStamp"
        case terms = "Terms"
        case useDebitAmount = "UseDebitAmount"
        case wpcPin = "WPC_PIN"
        case wpcPublish = "WPC_Publish"
    }
}

struct CustomField: Codable {
    let name: String
    let tab: String
    let value: String

    enum CodingKeys: String, CodingKey {
        case name = "Name"
        case tab = "Tab"
        case value = "Value"
    }
}

struct PrimaryBorrower: Codable {
    let account, borrowerRecID, city, deliveryOptions: String
    let emailAddress, emailFormat, firstName, fullName: String
    let lastName, mi, phoneCell, phoneFax: String
    let phoneHome, phoneWork, placeOnHold, recID: String
    let rolodexPrint, salutation, sendLateNotices, sendPaymentReceipt: String
    let sendPaymentStatement, state, street, tin: String
    let tinType, zipCode: String

    enum CodingKeys: String, CodingKey {
        case account = "Account"
        case borrowerRecID = "BorrowerRecID"
        case city = "City"
        case deliveryOptions = "DeliveryOptions"
        case emailAddress = "EmailAddress"
        case emailFormat = "EmailFormat"
        case firstName = "FirstName"
        case fullName = "FullName"
        case lastName = "LastName"
        case mi = "MI"
        case phoneCell = "PhoneCell"
        case phoneFax = "PhoneFax"
        case phoneHome = "PhoneHome"
        case phoneWork = "PhoneWork"
        case placeOnHold = "PlaceOnHold"
        case recID = "RecID"
        case rolodexPrint = "RolodexPrint"
        case salutation = "Salutation"
        case sendLateNotices = "SendLateNotices"
        case sendPaymentReceipt = "SendPaymentReceipt"
        case sendPaymentStatement = "SendPaymentStatement"
        case state = "State"
        case street = "Street"
        case tin = "TIN"
        case tinType = "TINType"
        case zipCode = "ZipCode"
    }
}

Upvotes: 1

Related Questions