I am running a vapor server. My app network requests are all working perfectly except for getOrders. When running the request on Postman it returns successfully. Can anyone see what Postman does to get a response that I am failing to do?
This is the error I'm currently getting:
typeMismatch(Swift.Double, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "dateOrdered", intValue: nil)], debugDescription: "Expected to decode Double but found a string instead.", underlyingError: nil))
Here's my network request code:
func getOrders() async throws -> [Order] {
let session = URLSession.shared
var request = URLRequest(url: URL(string: "\(API.url)/orders/")!)
request.httpMethod = "GET"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer \(token!.value)", forHTTPHeaderField: "Authorization")
// Make the request
let (data, response) = try await session.data(for: request)
print(data)
print(response)
// Ensure we had a good response (status 200)
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
throw GetOrdersError.unableToGetOrders
}
print(httpResponse.statusCode)
let decoder = JSONDecoder()
let orders = try decoder.decode([Order].self, from: data)
print(orders)
return orders
}
Here's the Order model in my app:
struct Order: Identifiable, Codable {
var id: UUID?
var residentID: UUID
var house: String
var dateOrdered: Date
var allPurposeCleaner: Bool
var airFreshener: Bool
var laundryPods: Bool
var dishPods: Bool
var dishSoap: Bool
var windex: Bool
var cloroxWipes: Bool
var paperTowels: Bool
var toiletPaper: Bool
var toiletBowlCleaner: Bool
var thrift: Bool
var swifferPads: Bool
var trashBags: Bool
var isOrderCompleted: Bool
static let houses = ["Wolf Pack", "Crow House", "Raptor House", "Lemur House", "Orca Pod", "Gorilla House", "Bison House", "Lion's Den"]
init(id: UUID?, residentID: UUID, house: String, dateOrdered: Date, allPurposeCleaner: Bool, airFreshener: Bool, laundryPods: Bool, dishPods: Bool, dishSoap: Bool, windex: Bool, cloroxWipes: Bool, paperTowels: Bool, toiletPaper: Bool, toiletBowlCleaner: Bool, thrift: Bool, swifferPads: Bool, trashBags: Bool, isOrderCompleted: Bool) {
self.id = id
self.residentID = residentID
self.house = house
self.dateOrdered = dateOrdered
self.allPurposeCleaner = allPurposeCleaner
self.airFreshener = airFreshener
self.laundryPods = laundryPods
self.dishPods = dishPods
self.dishSoap = dishSoap
self.windex = windex
self.cloroxWipes = cloroxWipes
self.paperTowels = paperTowels
self.toiletPaper = toiletPaper
self.toiletBowlCleaner = toiletBowlCleaner
self.thrift = thrift
self.swifferPads = swifferPads
self.trashBags = trashBags
self.isOrderCompleted = isOrderCompleted
}
}
Here's the Order model on my server:
import Foundation
import Vapor
import Fluent
final class Order: Model, Content {
init() {
}
static var schema: String = "orders"
init(id: UUID, residentID: UUID, house: String, dateOrdered: Date, allPurposeCleaner: Bool, airFreshener: Bool, laundryPods: Bool, dishPods: Bool, dishSoap: Bool, windex: Bool, cloroxWipes: Bool, paperTowels: Bool, toiletPaper: Bool, toiletBowlCleaner: Bool, thrift: Bool, swifferPads: Bool, trashBags: Bool, isOrderCompleted: Bool) {
self.id = id
self.residentID = residentID
self.house = house
self.dateOrdered = dateOrdered
self.allPurposeCleaner = allPurposeCleaner
self.airFreshener = airFreshener
self.laundryPods = laundryPods
self.dishPods = dishPods
self.dishSoap = dishSoap
self.windex = windex
self.cloroxWipes = cloroxWipes
self.paperTowels = paperTowels
self.toiletPaper = toiletPaper
self.toiletBowlCleaner = toiletBowlCleaner
self.thrift = thrift
self.swifferPads = swifferPads
self.trashBags = trashBags
self.isOrderCompleted = isOrderCompleted
}
@ID(key: .id)
var id: UUID?
@Field(key: "residentID")
var residentID: UUID
@Field(key: "house")
var house: String
@Field(key: "dateOrdered")
var dateOrdered: Date
@Field(key: "allPurposeCleaner")
var allPurposeCleaner: Bool
@Field(key: "airFreshener")
var airFreshener: Bool
@Field(key: "laundryPods")
var laundryPods: Bool
@Field(key: "dishPods")
var dishPods: Bool
@Field(key: "dishSoap")
var dishSoap: Bool
@Field(key: "windex")
var windex: Bool
@Field(key: "cloroxWipes")
var cloroxWipes: Bool
@Field(key: "paperTowels")
var paperTowels: Bool
@Field(key: "toiletPaper")
var toiletPaper: Bool
@Field(key: "toiletBowlCleaner")
var toiletBowlCleaner: Bool
@Field(key: "thrift")
var thrift: Bool
@Field(key: "swifferPads")
var swifferPads: Bool
@Field(key: "trashBags")
var trashBags: Bool
@Field(key: "isOrderCompleted")
var isOrderCompleted: Bool
}
Here's Postman working fine:
try this approach using a specific date decoder, adjust if your dates are not iso8601:
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601 // <-- here
let orders = try decoder.decode([Order].self, from: data)
To use your own date format, use
decoder.dateDecodingStrategy = .formatted(myDateFormat)