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

Swift中URLSession结合Combine解码JSON数组失败问题解决

问题:Combine的URLSession.dataTaskPublisher无法解码JSON数组

调用服务接口时获取到JSON数组,但无法通过Combine的URLSession.shared.dataTaskPublisher完成解码。项目采用Data、Domain、Presentation分层架构(基于GitHub上的CiMA混合Viper架构)。

原请求代码:

public func getGasStationDiscounts(requestModel: GasStationDiscountsRequestDomainModel) -> CiMAObservable<GasStationDiscountsDomainModel> {
    guard let url = URL(string: RepositoryConstants.baseURL + String(format: RepositoryConstants.EndPoints.gasStationDiscounts, requestModel.gasStationID)) else {
        return Fail(error: NSError(domain: "URL Invalid", code: 001, userInfo: nil)).eraseToAnyPublisher()
    }
    
    var urlRequest = URLRequest(url: url)
    urlRequest.httpMethod = "GET"
    urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
    urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
    
    return URLSession.shared.dataTaskPublisher(for: urlRequest)
        .map(\.data)
        .decode(type: GasStationDiscountsDataModel.self, decoder: JSONDecoder())
        .map { model -> GasStationDiscountsDomainModel in
            model.parseToDomainModel()
        }.eraseToAnyPublisher()
}

原可解码模型说明:
原GasStationDiscountsDataModel是针对单个对象的解码模型,但接口实际返回的是该对象组成的JSON数组,导致解码结构不匹配。


已解决!
找到不破坏现有架构的解决方案,调整如下:

可解码模型修改

将原GasStationDiscountsDataModel调整为对应数组中单个元素的结构,确保其能正确解码数组内的每一项数据。

修改后的请求代码

public func getGasStationDiscounts(requestModel: GasStationDiscountsRequestDomainModel) -> CiMAObservable<GasStationDiscountsDomainModel> {
    guard let url = URL(string: RepositoryConstants.baseURL + String(format: RepositoryConstants.EndPoints.gasStationDiscounts, requestModel.gasStationID)) else {
        return Fail(error: NSError(domain: "URL Invalid", code: 001, userInfo: nil)).eraseToAnyPublisher()
    }
    
    var urlRequest = URLRequest(url: url)
    urlRequest.httpMethod = "GET"
    urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
    urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
    
    return URLSession.shared.dataTaskPublisher(for: urlRequest)
        .map(\.data)
        .decode(type: [GasStationDiscountsDataModel].self, decoder: JSONDecoder())
        .map { model -> GasStationDiscountsDomainModel in
            let stationDiscountsDomainModel = model.map { model -> StationDiscountDomainModel in
                model.parseToDomainModel()
            }
            return GasStationDiscountsDomainModel(stationDiscounts: stationDiscountsDomainModel)
        }
        .mapError { error in
            print(error.localizedDescription)
            return error
        }.eraseToAnyPublisher()
}

关键修改点

  1. 解码类型从GasStationDiscountsDataModel.self改为[GasStationDiscountsDataModel].self,匹配接口返回的数组结构
  2. 在map操作中遍历解码后的数组,将每个DataModel转换为对应的DomainModel,再封装到GasStationDiscountsDomainModel中,适配分层架构要求
  3. 添加mapError处理,便于调试解码过程中的错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 18:16:06