首页 > 解决方案 > 预期的数组,但在 Swift 中找到了 Dictionary

问题描述

我是 Swift 中 Codable 的新手,我正在尝试从 API ( https://sportspagefeeds.com/documentation ) 获取一些数据。我不需要从 API 中获取所有数据,只需在模型中指定字段即可。尝试运行我的代码时出现此错误:typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))

奇怪的是,当我将 API 响应放在一个字符串中然后对其进行编码时,我可以使用相同的确切代码成功地对其进行解码。有人对这里有任何见解吗?我200从响应中得到一个代码

代码:

let request = NSMutableURLRequest(url: NSURL(string: "https://sportspage-feeds.p.rapidapi.com/games?league=NBA")! as URL,
                                                cachePolicy: .useProtocolCachePolicy,
                                            timeoutInterval: 10.0)
        request.httpMethod = "GET"
        request.allHTTPHeaderFields = headers
        
        let session = URLSession.shared
        session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
            
            if let data = data {
                do {
                    let dec = JSONDecoder()
                    dec.keyDecodingStrategy = .convertFromSnakeCase
                    let games = try dec.decode([Game].self, from: data)
                    print(games)
                    
                } catch {
                    print(error)
                    
                }
   
            }
        }).resume()

API返回结构(来自链接):

[
    {
        "gameId":"tv7mnr2-g7c4fe5-p95kxge-ptyhr72" ,
        "details":{
            "league":"NFL" ,
            "season":2018 ,
            "seasonType":"regular" ,
            "conferenceGame":true ,
            "divisionGame":true
        } ,
        "schedule":{
            "date":"2018-12-30T18:00:00.000Z" ,
            "tbaTime":false
        } ,
        "teams":{
            "away":{
                "team":"Miami Dolphins" ,
                "location":"Miami" ,
                "mascot":"Dolphins" ,
                "abbreviation":"MIA" ,
                "conference":"AFC" ,
                "division":"East"
            } ,
            "home":{
                "team":"Buffalo Bills" ,
                "location":"Buffalo" ,
                "mascot":"Bills" ,
                "abbreviation":"BUF" ,
                "conference":"AFC" ,
                "division":"East"
            }
        } ,
        "venue":{
            "name":"New Era Field" ,
            "city":"Orchard Park" ,
            "state":"NY" ,
            "neutralSite":false
        } ,
        "scoreboard":{
            "score":{
                "away":17 ,
                "home":42 ,
                "awayPeriods": [0 ,14 ,3 ,0] ,
                "homePeriods": [14 ,0 ,14 ,14]
            } ,
            "currentPeriod":4 ,
            "periodTimeRemaining":"0:00"
        } ,

[ etc...... ]

]

这是我的模型:

public struct Game: Codable {
    public var gameId: String?
    public var details: Details?
    public var teams: Teams?
    public var scoreboard: Scoreboard?
}

public struct Details: Codable {
    public var league: String?
    
}

public struct Teams: Codable {
    public var home: Team?
    public var away: Team?
}

public struct Team: Codable {
    public var team: String?
    public var abbreviation: String?
}

public struct Scoreboard: Codable {
    public var score: Score?
    public var currentPeriod: Int?
    public var periodTimeRemaining: String?
}

public struct Score: Codable {
    public var away: Int?
    public var home: Int?
}

标签: iosswiftcodablensurlrequest

解决方案


让我们看看 api 的响应:

    "status": 200,
    "time": "2021-03-26T01:42:14.010Z",
    "games": 5,
    "skip": 0,
    "results": [....]

响应是 Dictionary,但您将其编码为 [Game] 数组,这就是您收到此错误的原因。您需要创建更多这样的模型

public struct GameResponse: Codable {
    var status: Int
    var time: String
    var games: Int
    var skip: Int
    var results: [Game]

}

并解码对 GameResponseModel 的响应:

    let games = try dec.decode(GameResponse.self, from: data)

并将您的游戏 id 更改为 Int,因为它是 Int 而不是 String

public struct Game: Codable {
    public var gameId: Int?
    public var details: Details?
    public var teams: Teams?
    public var scoreboard: Scoreboard?
}

推荐阅读