Swift解析单条JSON响应遇类型不匹配错误,求解决方案
解决Swift Codable解码类型不匹配问题(Expected to decode Array but found a dictionary)
解码错误信息:
typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "document", intValue: nil)], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))
核心问题
返回的JSON中,document字段对应的是单个字典对象,但你定义的JobIdAPI结构体将其声明为数组类型[JobById],直接导致解码时类型不匹配。
具体修正步骤
1. 修正Codable结构体定义
将JobIdAPI中的document类型从数组改为单个JobById对象:
// MARK: - Job ID struct JobIdAPI: Codable { let status: String let code: Int let message: String let document: JobById // 从[JobById]修改为JobById } struct JobById: Codable, Identifiable { let id: String let jobUniqid: String? let jobClientJobNo: String? let jobPriority: String? let jobQuoteNo: String? let jobInvoiceNo: String? let jobStatus: String? let jobAgentId: String? let jobAddr1: String? let jobAddr2: String? let jobTownCity: String? let jobCounty: String? let jobPostcode: String? let jobContactName1: String? // 剩余字段... enum CodingKeys: String, CodingKey { case id = "ID" case jobUniqid = "job_uniqid" case jobClientJobNo = "job_client_job_no" case jobPriority = "job_priority" case jobQuoteNo = "job_quote_no" case jobInvoiceNo = "job_invoice_no" case jobStatus = "job_status" case jobAgentId = "job_agent_id" case jobAddr1 = "job_addr_1" case jobAddr2 = "job_addr_2" case jobTownCity = "job_town_city" case jobCounty = "job_county" case jobPostcode = "job_postcode" case jobContactName1 = "job_contact_name_1" // 剩余CodingKeys... } }
2. 修正@State变量声明
原代码中@State var jobRecordId = JobById是错误写法,改为可选类型适配初始无数据的状态:
@State var jobRecordId: JobById?
3. 修正请求与解码逻辑
同时优化异步代码,用Swift原生async/await替代回调式dataTask,提升代码可读性:
func loadData() async { guard let url = URL(string: "https://api.badsey.app/\(MemberCheck)/API/dp_jobs/read_one.php?id=\(LastJobID)") else { print("Invalid URL") return } var request = URLRequest(url: url) request.httpMethod = "GET" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue("Bearer \(TokenCheck)", forHTTPHeaderField: "Authorization") do { let (data, response) = try await URLSession.shared.data(for: request) // 可选:验证响应状态码 guard (response as? HTTPURLResponse)?.statusCode == 200 else { print("Invalid response status code") return } let decodedResponse = try JSONDecoder().decode(JobIdAPI.self, from: data) DispatchQueue.main.async { self.jobRecordId = decodedResponse.document } } catch { print("Request or decoding error: \(error)") } }
额外说明
- 若后续API可能返回数组格式的
document,可自定义解码逻辑让结构体同时兼容数组和单个对象,但根据当前提供的JSON,只需处理单个对象场景。 - 使用
async/await时,需在异步上下文调用loadData(),比如通过.task修饰符或按钮的action: { await loadData() }。
内容的提问来源于stack exchange,提问作者Badsey
相关产品推荐
相关产品推荐

