You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 00:09:05