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

使用Alamofire和JSONDecoder解析iTunes API时无法获取response.data如何解决

问题根因
  • 你封装的网络层使用Alamofire的responseJSON方法处理响应,回调返回的是已经序列化完成的Any类型JSON结果,既不是原始响应Data数据,也不是Alamofire原生Response对象,因此外部接收的response参数不存在.data属性,调用自然失败。
  • JSONDecoder解析要求传入原始Data类型数据,你当前拿到的序列化后字典/数组无法直接输入给JSONDecoder。
调整方案

方案1:修改网络层返回原始Data(更推荐,无额外性能损耗)

第一步:修改AlamofireLayer代码

将responseJSON替换为responseData,直接返回原始响应数据:

import Foundation
import Alamofire

enum MethodType {
    case get
    case post
}

class AlamofireLayer{
    class func requestData(_ type : MethodType, URLString : String, parameters : [String : Any]? = nil, finishedCallback :  @escaping (_ result: Data?, _ error: Error?) -> ()) {
        
        let method = type == .get ? HTTPMethod.get : HTTPMethod.post
        
        Alamofire.AF.request(URLString, method: method, parameters: parameters).responseData { (response) in
               
            switch response.result {
            case .success(let data):
                finishedCallback(data, nil)
                break
            case .failure(let error):
                finishedCallback(nil, error)
                break
            }
            
        }
    }
}

第二步:修改协议层与实现层适配新回调

import Foundation
import SwiftyJSON

protocol NetworkUtil {
    static func postRequest(URLString: String, parameters : [String : Any]?, callback: @escaping (_ data: Data?, _ error: Error?) -> ())
    static func getRequest(URLString: String, parameters : [String : Any]?,callback: @escaping (_ data: Data?, _ error: Error?) -> ())
}

class NetworkImpl: NetworkUtil{
    
    static func getRequest(URLString: String, parameters: [String : Any]?, callback: @escaping (Data?, Error?) -> ()) {
        AlamofireLayer.requestData(MethodType.get, URLString: URLString, parameters: parameters) { data, error in
            callback(data, error)
        }
    }
    
    public static func postRequest(URLString: String, parameters: [String : Any]?, callback: @escaping (Data?, Error?) -> ()) {
        AlamofireLayer.requestData(MethodType.post, URLString: URLString, parameters: parameters) { data, error in
            callback(data, error)
        }
    }
  
}

第三步:修改业务调用代码

let url = "https://itunes.apple.com/search?"
NetworkImpl.getRequest(URLString: url, parameters: ["term": searchBar.text!, "entity": "software", "country": "cn", "limit": "200"]) { data, error in
    guard let data = data, error == nil else {
        print("请求失败: \(error!)")
        return
    }
    do{
        let decoder = JSONDecoder()
        let newModel = try decoder.decode(NewModel.self, from: data)
        print("------> \(newModel.resultCount)")
    } catch {
        print("解析失败: \(error)")
    }
}

补充:NewModel结构要匹配iTunes API返回格式,示例如下:

struct NewModel: Codable {
    let resultCount: Int
    let results: [SoftwareItem]
}

struct SoftwareItem: Codable {
    let trackName: String?
    let artistName: String?
    // 其他需要的字段自行补充
}

方案2:不改动现有网络层的兼容方案

如果不想修改已封装的网络层逻辑,可以把当前回调拿到的序列化后JSON对象重新转回Data再解析:

let url = "https://itunes.apple.com/search?"
NetworkImpl.getRequest(URLString: url, parameters: ["term": searchBar.text!, "entity": "software", "country": "cn", "limit": "200"]) { (response) in
    do{
        // 把Any类型的JSON序列化为Data
        let jsonData = try JSONSerialization.data(withJSONObject: response)
        let decoder = JSONDecoder()
        let newModel = try decoder.decode(NewModel.self, from: jsonData)
        print("------> \(newModel.resultCount)")
    } catch {
        print(error)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 03:51:04