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

HTTP请求处理类优化需求:实现通用JSON转字典功能

优化通用HTTP请求类的思路与实现

嘿,很高兴看到你在尝试封装通用的HTTP请求类!你当前用JSONSerialization的写法确实有点繁琐:不仅要写重复的解析代码,try?还会悄悄吞掉错误,[String:Any]的无类型字典后续使用也容易出问题。下面给你几个优化方向,让这个类更通用、更易用:

1. 用Codable实现类型安全的解析

Swift的Codable协议是处理JSON的绝佳工具,它能帮你直接把JSON转成自定义模型,完全避免无类型字典的强制转换问题,类型安全还省代码。

2. 封装通用的请求方法

我们可以把请求、解析、错误处理全部封装到一个通用方法里,支持不同的HTTP方法、自定义请求头和请求体,同时用Result类型清晰区分成功和失败场景。

完整示例代码

import Foundation

// 定义明确的错误枚举,方便调试和处理
enum HTTPError: Error {
    case invalidURL
    case requestFailed(Error)
    case invalidResponse
    case noData
    case parsingFailed(Error)
    case notADictionary
}

class HTTPClient {
    // 单例模式方便全局调用,也可以改成初始化方法灵活配置
    static let shared = HTTPClient()
    
    private init() {}
    
    /// 通用请求方法,支持解析成任意Codable模型
    func fetch<T: Codable>(
        urlString: String,
        method: String = "GET",
        headers: [String: String]? = nil,
        body: Data? = nil,
        completion: @escaping (Result<T, HTTPError>) -> Void
    ) {
        guard let url = URL(string: urlString) else {
            completion(.failure(.invalidURL))
            return
        }
        
        var request = URLRequest(url: url)
        request.httpMethod = method
        headers?.forEach { request.setValue($0.value, forHTTPHeaderField: $0.key) }
        request.httpBody = body
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            // 处理网络请求错误
            if let error = error {
                completion(.failure(.requestFailed(error)))
                return
            }
            
            // 验证响应状态码
            guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
                completion(.failure(.invalidResponse))
                return
            }
            
            // 确保有返回数据
            guard let data = data else {
                completion(.failure(.noData))
                return
            }
            
            // 解析成目标模型
            do {
                let decodedObject = try JSONDecoder().decode(T.self, from: data)
                completion(.success(decodedObject))
            } catch {
                completion(.failure(.parsingFailed(error)))
            }
        }.resume()
    }
    
    /// 重载方法,支持直接返回字典(兼容你原本的需求)
    func fetchDictionary(
        urlString: String,
        method: String = "GET",
        headers: [String: String]? = nil,
        body: Data? = nil,
        completion: @escaping (Result<[String: Any], HTTPError>) -> Void
    ) {
        // 先获取原始数据,再转成字典
        fetch(urlString: urlString, method: method, headers: headers, body: body) { (result: Result<Data, HTTPError>) in
            switch result {
            case .success(let data):
                do {
                    guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
                        completion(.failure(.notADictionary))
                        return
                    }
                    completion(.success(json))
                } catch {
                    completion(.failure(.parsingFailed(error)))
                }
            case .failure(let error):
                completion(.failure(error))
            }
        }
    }
}

// --- 使用示例 ---
// 1. 类型安全的模型解析
struct User: Codable {
    let id: Int
    let name: String
    let email: String
}

HTTPClient.shared.fetch(urlString: "https://api.example.com/users/1") { (result: Result<User, HTTPError>) in
    switch result {
    case .success(let user):
        print("用户:\(user.name),邮箱:\(user.email)")
    case .failure(let error):
        print("请求失败:\(error)")
    }
}

// 2. 直接获取字典
HTTPClient.shared.fetchDictionary(urlString: "https://api.example.com/config") { result in
    switch result {
    case .success(let configDict):
        print("配置信息:\(configDict)")
    case .failure(let error):
        print("获取配置失败:\(error)")
    }
}

3. 适配更多场景的小技巧

  • 支持自定义配置:可以给HTTPClient添加初始化方法,允许传入自定义的URLSession(比如配置超时时间、代理等)
  • 添加缓存逻辑:可以根据业务需求增加请求缓存,减少重复请求
  • 支持批量请求:封装批量请求的方法,等待所有请求完成后统一返回结果
  • 进度回调:如果需要上传/下载进度,可以添加对应的进度闭包

这样封装后的类,既支持类型安全的模型解析(推荐用于大部分业务场景),又兼容你原本需要字典的需求,错误处理清晰,还能灵活扩展适配更多业务场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:12:31