如何利用泛型Response结构体解码通用响应中的数据?
泛型Response结构体解码数组数据的修正方案
问题梳理
你的代码存在几个关键问题导致无法正确解码:
- Mock JSON存在语法错误(数组元素末尾多余逗号)
Pokemon遵循Identifiable但未实现id属性loadData函数中类型不匹配(期望返回[Value],但解码时用Response<Value>,而实际data是数组类型)- 缺失
request变量定义和NetworkError枚举
修正后的完整代码
// 修正JSON格式,移除多余逗号 let mockData = """ { "status": "ok", "data": [ { "name": "Pikachu" }, { "name": "Squirtle" }, { "name": "Eevee" } ] } """.data(using: .utf8)! // 泛型Response结构体保持不变 struct Response<T: Decodable>: Decodable { let status: String let data: T } // 补充NetworkError枚举定义 enum NetworkError: Error { case invalidPayLoad case invalidRequest } // EndPoint补充url属性,用于构建请求 public enum EndPoint: String { case characters = "your-api-url-here" var url: URL { URL(string: rawValue)! // 实际项目中建议处理可选绑定 } } protocol APIManagerProtocol { func loadData<Value: Decodable>(endPoint: EndPoint) async throws -> [Value] } actor APIManager: APIManagerProtocol { static let shared = APIManager() private let session = URLSession.shared private let decoder = JSONDecoder() func loadData<Value: Decodable>(endPoint: EndPoint) async throws -> [Value] { // 构建请求 let request = URLRequest(url: endPoint.url) // 实际请求数据(这里暂时用mockData代替,可注释掉换成下面的真实请求) let data = mockData // let (data, response) = try await session.data(for: request) // 解码为Response<[Value]>,因为data是数组类型 let payload = try decoder.decode(Response<[Value]>.self, from: data) guard payload.status == "ok" else { throw NetworkError.invalidPayLoad } return payload.data } } // 修正Pokemon结构体,添加id属性(Identifiable要求) struct Pokemon: Identifiable, Decodable { let id = UUID() // 自动生成UUID作为id let name: String } // 调用示例 func fetchPokemon() async { let api = APIManager.shared do { let pokemon = try await api.loadData(endPoint: .characters) print(pokemon) } catch { print(error) } }
关键修改说明
- JSON修正:删除数组元素末尾的逗号,避免JSON解析失败。
- Pokemon结构体:添加
id属性满足Identifiable协议要求,这里用UUID()自动生成,也可以根据业务逻辑用name作为id(需确保唯一)。 - loadData函数:
- 补充
request变量的构建,基于EndPoint的url属性生成请求。 - 解码时指定
Response<[Value]>.self,因为接口返回的data是数组类型,这样payload.data直接就是[Value],符合函数返回类型。 - 使用成员变量
decoder而不是每次创建新的JSONDecoder,更高效。
- 补充
- 补充必要定义:添加
NetworkError枚举和EndPoint的url属性,让代码完整可运行。
内容的提问来源于stack exchange,提问作者rb2030
相关产品推荐
相关产品推荐

