Alamofire解析API返回数组至[Artist]模型失败的问题求助
解决Alamofire解码API数组为Swift模型失败的问题
你遇到的这个解码错误其实很典型,咱们先抓错误信息里的核心提示:Expected to decode Dictionary<String, Any> but found an array instead——这说明你的解码目标类型和API返回的数据结构完全不匹配,再结合你的代码和API返回的JSON,咱们一步步修复:
1. 修正解码目标类型
API返回的是直接的Artist对象数组([{}]),但你现在用[ArtistsResponse].self来解码,而ArtistsResponse结构体要求的是一个包含artists字段的字典(比如{"artists": [{}]}),这就导致了解码器期望字典但拿到数组的冲突。
直接去掉多余的ArtistsResponse结构体,把请求的解码类型改成[Artist].self:
AF.request(Constants.kGetArtistsAPIEndPoint).responseDecodable(of: [Artist].self) { (response) in guard let artists = response.value else { // 这里可以补充错误处理,比如打印response.error排查问题 return } print("Fetched \(artists.count) artists") completion(artists) // 注意completion的参数类型要同步改成[Artist] }
2. 修正Artist模型的字段映射
你的Artist结构体里有两处映射错误,会导致字段解码失败:
emailId对应API里的email字段,但当前CodingKeys里没指定映射关系;- API里的
id是数字类型(Int),但你模型里定义的artistId是String,直接解码会类型不匹配。
修改后的Artist模型:
struct Artist: Codable { let artistId: Int // 改成Int匹配API的数字类型,后续需要String可以再转换 let name: String let username: String? let emailId: String? let address: Address? let phone: String? let website: String? let company: Company? enum CodingKeys: String, CodingKey { case artistId = "id" case name case username case emailId = "email" // 补上email字段的映射 case address case phone case website case company } }
3. 修复GeoLocation的字符串转Double问题
API里的lat和lng是字符串格式(比如"-37.3159"),但你模型里定义的是Double类型,默认Codable无法直接把字符串转成数字,这里提供两种解决方案:
方式一:先存字符串,用计算属性转Double
struct GeoLocation: Codable { let latitude: String let longitude: String enum CodingKeys: String, CodingKey { case latitude = "lat" case longitude = "lng" } // 可选:提供计算属性方便后续使用Double类型 var latDouble: Double? { Double(latitude) } var lngDouble: Double? { Double(longitude) } }
方式二:自定义解码逻辑,直接转成Double
struct GeoLocation: Codable { let latitude: Double let longitude: Double enum CodingKeys: String, CodingKey { case latitude = "lat" case longitude = "lng" } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 先解码成String,再转成Double,转换失败抛出明确错误 let latString = try container.decode(String.self, forKey: .latitude) guard let latDouble = Double(latString) else { throw DecodingError.dataCorruptedError(forKey: .latitude, in: container, debugDescription: "Latitude string cannot be converted to Double") } latitude = latDouble let lngString = try container.decode(String.self, forKey: .longitude) guard let lngDouble = Double(lngString) else { throw DecodingError.dataCorruptedError(forKey: .longitude, in: container, debugDescription: "Longitude string cannot be converted to Double") } longitude = lngDouble } }
4. 最后检查点
- 确保
Address结构体的可选字段定义正确(比如suite设为String?是合理的); - 补充
Company结构体的定义,确保它的字段和API返回的company对象完全匹配并实现Codable。
修改完以上内容后,应该就能成功把API返回的数组解码成[Artist]模型数组了。
内容的提问来源于stack exchange,提问作者Karthick Ramesh
相关产品推荐
相关产品推荐

