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

如何使用Alamofire 5解析JSON数组?

Alamofire 5 JSON数组解码失败求助

问题概述

使用Alamofire 5解析JSON数组时持续失败,尝试过responseString、responseData、responseJSON及responseDecodable搭配Codable模型等多种方式,均无法正常解析。错误提示显示"期望解码Array但找到字符串/数据"。

返回的JSON示例

[
    {
        "Date": "2022-08-08T00:00:00",
        "Day": "Fri",
        "AbsenceCount": 0,
        "AbsenceRequestComments": "Request permitted",
        "Color": "No",
        "IsRequestPermitted": true
    },
    {
        "Date": "2022-09-09T00:00:00",
        "Day": "Sat",
        "AbsenceCount": 0,
        "AbsenceRequestComments": "Request permitted",
        "Color": "No",
        "IsRequestPermitted": true
    },
    {
        "Date": "2022-12-15T00:00:00",
        "Day": "Sun",
        "AbsenceCount": 0,
        "AbsenceRequestComments": "Request permitted",
        "Color": "No",
        "IsRequestPermitted": true
    }
]

请求代码

let request = AF.request(requestURL, method: .get, parameters: parameters, encoding: URLEncoding.default, headers: returnHeader())
    .validate()
    .responseDecodable(of: [CoverCheckForDay].self) { response in
        switch response.result {
        case .success:
            guard let value = response.value else { failure(""); return }
            success(value)
        case .failure(let error):
            failure(error.localizedDescription)
        }
    }

Codable模型定义

struct CoverCheckForDay: Codable {
    let date: String
    let day: String
    let absenceCount: Int
    let absenceRequestComments: String
    let color: String
    let isRequestPermitted: Bool

    enum CodingKeys: String, CodingKey {
        case date = "Date"
        case day = "Day"
        case absenceCount = "AbsenceCount"
        case absenceRequestComments = "AbsenceRequestComments"
        case color = "Color"
        case isRequestPermitted = "IsRequestPermitted"
    }
}

错误信息

▿ Optional<AFError>
  ▿ some : AFError
    ▿ responseSerializationFailed : 1 element
      ▿ reason : ResponseSerializationFailureReason
        ▿ decodingFailed : 1 element
          ▿ error : DecodingError
            ▿ typeMismatch : 2 elements
              - .0 : Swift.Array<Any>
              ▿ .1 : Context
                - codingPath : 0 elements
                - debugDescription : "Expected to decode Array<Any> but found a string/data instead."
                - underlyingError : nil

请求参数

▿ 3 elements
  ▿ 0 : 2 elements
    - key : "employeeId"
    - value : 13558
  ▿ 1 : 2 elements
    - key : "dates"
    ▿ value : 3 elements
      ▿ 0 : CoverRequestArray
        ▿ date : Optional<String>
          - some : "01/09/2022"
        ▿ day : Optional<String>
          - some : "Thu"
      ▿ 1 : CoverRequestArray
        ▿ date : Optional<String>
          - some : "02/09/2022"
        ▿ day : Optional<String>
          - some : "Fri"
      ▿ 2 : CoverRequestArray
        ▿ date : Optional<String>
          - some : "03/09/2022"
        ▿ day : Optional<String>
          - some : "Sat"
  ▿ 2 : 2 elements
    - key : "siteId"
    - value : 440

排查与解决步骤

1. 确认服务器实际返回内容

服务器可能返回了转义后的字符串形式JSON(而非直接的JSON数组),先用responseData打印原始响应:

AF.request(requestURL, method: .get, parameters: parameters, encoding: URLEncoding.default, headers: returnHeader())
    .validate()
    .responseData { response in
        switch response.result {
        case .success(let data):
            if let rawStr = String(data: data, encoding: .utf8) {
                print("原始响应:\(rawStr)")
            }
        case .failure(let error):
            print(error)
        }
    }

如果打印结果带\"转义符,说明需要先将字符串转成Data再解码:

// 在responseData的success分支内处理
if let rawStr = String(data: data, encoding: .utf8), let fixedData = rawStr.data(using: .utf8) {
    do {
        let decodedResult = try JSONDecoder().decode([CoverCheckForDay].self, from: fixedData)
        success(decodedResult)
    } catch {
        failure(error.localizedDescription)
    }
}

2. 调整请求参数编码

当前使用URLEncoding.default,但服务器对数组参数的编码规则可能不匹配。尝试自定义数组编码方式:

// 可选编码方式:.brackets 生成 dates[]=xxx,.noBrackets 生成 dates=xxx
let customEncoding = URLEncoding(arrayEncoding: .brackets)
AF.request(requestURL, method: .get, parameters: parameters, encoding: customEncoding, headers: returnHeader())

3. 增强模型兼容性

临时将模型属性改为可选类型,排查是否存在字段为null导致的解码失败:

struct CoverCheckForDay: Codable {
    let date: String?
    let day: String?
    let absenceCount: Int?
    let absenceRequestComments: String?
    let color: String?
    let isRequestPermitted: Bool?

    enum CodingKeys: String, CodingKey {
        case date = "Date"
        case day = "Day"
        case absenceCount = "AbsenceCount"
        case absenceRequestComments = "AbsenceRequestComments"
        case color = "Color"
        case isRequestPermitted = "IsRequestPermitted"
    }
}

若解码成功,再逐个将可选属性改回非可选,定位问题字段。

内容的提问来源于stack exchange,提问作者Arsienij

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 16:58:56