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

Alamofire 5上传解码失败:提示数据缺失却实际存在的问题

Alamofire 5 上传解码失败问题解析

问题现象

使用Alamofire 5上传数据时,控制台提示「数据无法读取,因为数据缺失」,但上传的数据实际存在。控制台输出如下:

dic=== {"lat": "26.9342246", "message": "Test", "lng": "-80.0942087", "receiver_id": "269", "messageType": "text", "chatType": "fix", "product_variant_id": "", "receiverType": "customer", "customer_id": "213", "itemType": "sell", "product_id": "25", "service_id": "", "fileName": ""}
Result: failure(Alamofire.AFError.responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.decodingFailed(error: Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "message", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: "message", intValue: nil) ("message").", underlyingError: nil)))))
Upload Failed: Response could not be decoded because of error:
The data couldn’t be read because it is missing.

尝试将MessageModel中的message改为可选类型后,又出现「意外发现nil」错误,错误触发代码如下:

func sendChatProductImage(header: String, parameter: String, coverdata: UIImage, mimetype : String ,vc: UIViewController, showHud: Bool,completion : @escaping(_ success : Bool, _ message : String, _ response : NSDictionary) -> Void) {
    webService_obj.chatProductImageSend(header: header, withParameter: parameter, coverdata: coverdata, mimetypeExtention: mimetype, inVC: vc, showHud: showHud) { (response, success) in
        if success{
            let message = response["message"]
            completion(success, message as! String, response )
        }
    }
}

相关代码定义

Decodable 结构体

struct MessageModel : Decodable {
    let data : [MessageModelData]?
    let message : String
    
    enum CodingKeys: String, CodingKey {
        case message, data
    }
}

struct  MessageModelData : Decodable {
    let fileType : String
    let groupID, id : Int
    let intetestCustomerID, itemType, message, messageType : String
    let productID, productOwnerID, profileImg, profileName :String
    let receiveID, receiverType, sendAt : String
    
    enum CodingKeys: String, CodingKey {
        case groupID = "groupId"
        case intetestCustomerID = "intetest_customer_id"
        case productID = "product_id"
        case productOwnerID  = "product_owner_id"
        case receiveID = "receiveId"
        case fileType, id, itemType, message, messageType, profileImg, profileName, receiverType, sendAt
    }
}

Alamofire 上传代码

AF.upload(
    multipartFormData: { multipartFormData in
        var dic = parameter.replacingOccurrences(of: "[", with: "{")
        dic = dic.replacingOccurrences(of: "]", with: "}")
        print("dic===",dic)
        multipartFormData.append("\(dic)".data(using: String.Encoding.utf8)!, withName: "data")
        if coverimageData != nil {
            multipartFormData.append(coverimageData!, withName: "file", fileName: "chatImage.jpg", mimeType: "*/*")
        }else{
            multipartFormData.append("".data(using: String.Encoding.utf8)!, withName: "file")
        }
},
    with: uploadUrl).responseDecodable(of: MessageModel.self) { response in
        print("Result: \(response)")
        
        if hud {
            Loader.init().hide(delegate: vc)
        }
        switch response.result {
        case .success(let result):
            let dataResponse = response.value(forKey: "data" as? NSDictionary)
            completion(dataResponse, true)
        case .failure(let error):
            let err = error.localizedDescription
            print("Upload Failed: \(err)")
            completion([:], false)
            self.presentAlertWithTitle(title: kAPPName, message: err, vc: vc)
            break
        }
    }

问题原因及修复方案

核心问题

  1. 解码结构不匹配:responseDecodable要求服务器返回的JSON结构与MessageModel完全一致,但实际返回的响应可能不符合该结构(比如message字段不存在、嵌套层级错误);同时上传代码中用字符串替换符号构造JSON的方式,容易产生格式错误,导致服务器无法正确解析请求,进而返回异常响应。
  2. 强制解包触发崩溃:将message改为可选类型后,代码中仍用message as! String强制解包,若服务器返回的message为nil或类型不匹配,就会触发nil崩溃。

修复步骤

1. 验证服务器真实响应结构

在解码失败的分支中打印原始响应数据,确认服务器返回的JSON格式:

case .failure(let error):
    if let data = response.data, let rawResponse = String(data: data, encoding: .utf8) {
        print("服务器原始响应:\(rawResponse)")
    }
    // 原有报错逻辑

根据实际返回结构调整MessageModel,比如将可能缺失的字段设为可选:

struct MessageModel : Decodable {
    let data : [MessageModelData]?
    let message : String? // 改为可选类型
}

2. 修复请求参数构造方式

放弃字符串替换的方式,直接将参数序列化为合法的JSON Data:

// 若parameter是字典类型
if let paramDict = try? JSONSerialization.jsonObject(with: parameter.data(using: .utf8)!) as? [String: Any],
   let paramData = try? JSONSerialization.data(withJSONObject: paramDict, options: []) {
    multipartFormData.append(paramData, withName: "data")
}
// 若parameter本身是合法JSON字符串,直接转Data
if let paramData = parameter.data(using: .utf8) {
    multipartFormData.append(paramData, withName: "data")
}

3. 替换强制解包为安全处理

在sendChatProductImage中对可选值做安全处理:

if success{
    let message = response["message"] as? String ?? "操作完成"
    completion(success, message, response )
}

4. 修正解码后的数据处理逻辑

直接使用解码后的result对象,避免KVC方式取值:

case .success(let result):
    let dataResponse = result.data as? NSDictionary ?? [:]
    completion(dataResponse, true)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 03:45:02