如何不创建顶层结构直接将JSON嵌套层数据解码为Swift结构体?
问题解答
问题1:能否直接解码嵌套对象、跳过顶层response结构?
可以,不需要额外定义包含顶层字段的包装结构体,直接操作Decoder的容器即可实现嵌套层数据的直接解码。
问题2:能否先校验顶层字段存在性再执行解码?
完全可以,正好适配你提到的「要么返回response要么返回error」的接口逻辑,校验逻辑可以和解码逻辑合并实现。
实现代码
1. 基础定义
首先定义你需要的业务结构体和错误结构体,不需要包含任何顶层字段:
// 业务数据结构体示例,对应response嵌套层的结构 struct User: Decodable { let name: String let id: Int } // 接口错误结构体示例,对应error嵌套层的结构 struct APIError: Decodable, Error { let code: Int let message: String } // 顶层字段的CodingKeys,不需要绑定到任何结构体 private enum TopCodingKeys: String, CodingKey { case response, error }
2. 基础解码实现
直接读取顶层容器判断字段类型,再解码对应嵌套层数据:
let jsonData: Data = ... // 接口返回的原始数据 let decoder = JSONDecoder() do { // 读取顶层字典容器 let topContainer = try decoder.container(keyedBy: TopCodingKeys.self) // 优先判断是否存在错误字段 if topContainer.contains(.error) { let apiError = try topContainer.decode(APIError.self, forKey: .error) // 处理业务错误逻辑 print("接口错误:\(apiError.message)") } // 再判断是否存在业务数据字段 else if topContainer.contains(.response) { let user = try topContainer.decode(User.self, forKey: .response) // 直接使用解码得到的业务对象,无需处理顶层结构 print("用户ID:\(user.id),用户名:\(user.name)") } // 两个字段都不存在的异常场景处理 else { throw NSError(domain: "APIParser", code: -1, userInfo: [NSLocalizedDescriptionKey: "响应格式非法"]) } } catch { // 处理解码失败等通用异常 print("解析失败:\(error.localizedDescription)") }
3. 通用封装(可选)
如果所有接口都是这个返回结构,可以封装为泛型方法简化调用:
func decodeAPIData<T: Decodable>(_ type: T.Type, from data: Data) throws -> T { let decoder = JSONDecoder() let topContainer = try decoder.container(keyedBy: TopCodingKeys.self) // 存在错误则直接抛出 if let apiError = try? topContainer.decode(APIError.self, forKey: .error) { throw apiError } // 解码业务数据返回 return try topContainer.decode(T.self, forKey: .response) } // 调用示例 do { let user = try decodeAPIData(User.self, from: jsonData) // 直接使用user对象 } catch let error as APIError { // 处理业务错误 } catch { // 处理解析错误 }
内容的提问来源于stack exchange,提问作者cyrmax
相关产品推荐
相关产品推荐

