You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 22:44:57