Postman GET请求成功,SwiftUI App GET请求出现解码错误求助
Vapor接口SwiftUI解码错误排查
问题概述
运行Vapor服务器时,getOrders接口在Postman中调用正常,但SwiftUI App调用时触发JSON解码错误,其他接口均工作正常。
错误信息
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))
相关代码
1. SwiftUI应用端网络请求代码
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") // 发起请求 let (data, response) = try await session.data(for: request) print(data) print(response) // 验证响应状态码 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 }
2. SwiftUI应用端Order模型
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 } }
3. Vapor服务器端Order模型
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 }
Postman请求验证

解决方案
错误核心是dateOrdered字段的格式不匹配:Vapor默认将Date序列化为ISO8601字符串,而Swift的JSONDecoder默认期望时间戳(Double类型),导致解码失败。
修复步骤:
在SwiftUI应用端配置JSONDecoder日期解码策略
修改网络请求代码中的JSONDecoder初始化部分,指定使用ISO8601格式解码日期:let decoder = JSONDecoder() decoder.dateDecodingStrategy = .iso8601 // 添加该行 let orders = try decoder.decode([Order].self, from: data)可选:统一服务器端日期序列化格式
若要确保Vapor输出的日期格式一致,可在服务器端configure.swift中配置ContentConfiguration:let contentConfig = ContentConfiguration.default() let jsonEncoder = JSONEncoder() jsonEncoder.dateEncodingStrategy = .iso8601 contentConfig.use(encoder: jsonEncoder, for: .json) app.content = contentConfig
验证
修改后重新运行SwiftUI App,调用getOrders接口即可正常解码dateOrdered字段。
内容的提问来源于stack exchange,提问作者AFinch
相关产品推荐
相关产品推荐

