iOS Swift使用Decodable解析LOL英雄详情JSON动态Key适配问题
动态Key类JSON的Decodable解析方案
你遇到的是JSON顶层存在动态未知Key的典型场景,Swift Decodable原生支持该场景的解析,无需手动枚举所有英雄ID作为CodingKeys,有两种常用解决方案:
方案1:直接用字典类型接收动态Key层(最推荐,改造成本最低)
拳头的单英雄详情接口返回数据本质是[英雄ID: 英雄详情]的字典结构,你无需额外定义外层DataClass结构体,直接将响应数据解码为[String: HeroDetail]类型即可,其中HeroDetail是你已经写好的单个英雄详情解析结构体,无需修改。
示例代码:
// 你原有已实现的单英雄详情结构体,不需要做任何调整 struct HeroDetail: Decodable { let id: String let name: String let title: String let stats: [String: Double] // 其他你需要的字段按需补充 } // 解析逻辑 do { // 直接解码为[String: HeroDetail]字典 let heroMap = try JSONDecoder().decode([String: HeroDetail].self, from: apiResponseData) // 当前请求的英雄ID你可以从拼接请求URL的参数里拿到,直接取对应值即可 let targetHeroId = "当前请求的英雄ID,例如ahri" guard let heroDetail = heroMap[targetHeroId] else { throw NSError(domain: "ParseError", code: -1, userInfo: [NSLocalizedDescriptionKey: "未找到对应英雄数据"]) } // 拿到英雄详情后做后续业务处理 } catch { print("解析失败:\(error.localizedDescription)") }
方案2:自定义解码初始化器适配动态Key(适合需要封装外层结构体的场景)
如果你需要统一封装响应结构,可以自定义动态CodingKey和解码初始化器实现解析,无需枚举所有英雄ID:
示例代码:
// 自定义外层响应结构体 struct SingleHeroResponse: Decodable { // 动态获取的英雄ID let heroId: String // 英雄详情 let detail: HeroDetail // 自定义动态CodingKey,支持任意字符串类型的Key private struct DynamicCodingKey: CodingKey { var stringValue: String var intValue: Int? init?(stringValue: String) { self.stringValue = stringValue self.intValue = nil } init?(intValue: Int) { self.stringValue = "\(intValue)" self.intValue = intValue } } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: DynamicCodingKey.self) // 单英雄接口仅返回1个键值对,直接取第一个Key即可 guard let firstKey = container.allKeys.first else { throw DecodingError.dataCorrupted(.init(codingPath: [], debugDescription: "响应数据无英雄信息")) } self.heroId = firstKey.stringValue self.detail = try container.decode(HeroDetail.self, forKey: firstKey) } } // 解析逻辑 do { let response = try JSONDecoder().decode(SingleHeroResponse.self, from: apiResponseData) print("英雄ID:\(response.heroId),英雄名称:\(response.detail.name)") } catch { print("解析失败:\(error.localizedDescription)") }
补充说明
- 两种方案都不需要调整你已写好的单英雄详情解析逻辑,仅需要修改外层的解析方式即可
- 如果你后续需要批量拉取全量英雄详情,方案1可以直接合并所有响应字典得到全量英雄ID到详情的映射表,使用效率更高
内容的提问来源于stack exchange,提问作者이진성
相关产品推荐
相关产品推荐

