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
相关产品推荐
相关产品推荐

