debugDescription: “Expected to decode Array but found a dictionary instead.”, underlyingError: nil)

前端 未结 3 634
粉色の甜心
粉色の甜心 2021-01-13 06:48

I want to load an online json file into my application, but I am running into this error:

typeMismatch(Swift.Array, Swift.DecodingError.Context(codi

相关标签:
3条回答
  • 2021-01-13 07:14

    Please learn to understand the decoding error messages, they are very descriptive.

    The error says you are going to decode an array but the actual object is a dictionary (the target struct).

    First take a look at the beginning of the JSON

    {
      "copyright" : "NHL and the NHL Shield are registered trademarks of the National Hockey League. NHL and NHL team marks are the property of the NHL and its teams. © NHL 2018. All Rights Reserved.",
      "totalItems" : 2,
      "totalEvents" : 0,
      "totalGames" : 2,
      "totalMatches" : 0,
      "wait" : 10,
      "dates" : [ {
        "date" : "2018-05-04",
    

    It starts with a { which is a dictionary (an array is [) but you want to decode an array ([Dates]), that's the type mismatch the error message is referring to.


    But this is only half the solution. After changing the line to try decoder.decode(Dates.self you will get another error that there is no value for key copyright.

    Look again at the JSON and compare the keys with the struct members. The struct whose members match the JSON keys is Initial and you have to get the dates array to populate gameData.

    let jsondata = try decoder.decode(Initial.self, from: detailData)
    gameData = jsondata.dates
    
    0 讨论(0)
  • 2021-01-13 07:14

    The JSON is represented by your Initial struct, not an array of Dates.

    Change:

    let jsondata = try decoder.decode([Dates].self, from: detailData)
    

    to:

    let jsondata = try decoder.decode(Initial.self, from: detailData)
    
    0 讨论(0)
  • 2021-01-13 07:32

    Correct Answer is done previously from my two friends

    but you have to do it better i will provide solution for you to make code more clean and will give you array of Dates

    here is your model with codable

       import Foundation
    
    struct Initial: Codable {
        let copyright: String
        let totalItems: Int
        let totalEvents: Int
        let totalGames: Int
        let totalMatches: Int
        let wait: Int
        let dates: [Dates]
    }
    
    struct Dates: Codable {
        let date: String
        let totalItems: Int
        let totalEvents: Int
        let totalGames: Int
        let totalMatches: Int
        let games: [Game]
    }
    
    struct Game: Codable {
        let gamePk: Int
        let link: String
        let gameType: String
        let season: String
        let gameDate: String
        let status: Status
        let teams: Team
        let venue: Venue
        let content: Content
    }
    
    struct Status: Codable {
        let abstractGameState: String
        let codedGameState: Int
        let detailedState: String
        let statusCode: Int
        let startTimeTBD: Bool
    }
    
    struct Team: Codable {
        let away: Away
        let home: Home
    }
    
    struct Away: Codable {
        let leagueRecord: LeagueRecord
        let score: Int
        let team: TeamInfo
    }
    
    struct Home: Codable {
        let leagueRecord: LeagueRecord
        let score: Int
        let team: TeamInfo
    }
    
    struct LeagueRecord: Codable {
        let wins: Int
        let losses: Int
        let type: String
    }
    
    struct TeamInfo: Codable {
        let id: Int
        let name: String
        let link: String
    }
    
    struct Venue: Codable {
        let name: String
        let link: String
    }
    
    struct Content: Codable {
        let link: String
    }
    
    // MARK: Convenience initializers
    
    extension Initial {
        init(data: Data) throws {
            self = try JSONDecoder().decode(Initial.self, from: data)
        }
    
    }
    

    And Here is Controller Will make solution more easy

    class ViewController: UIViewController {
        var todaysGamesURL: URL = URL(string: "https://statsapi.web.nhl.com/api/v1/schedule")!
    
        var gameData: Initial?
        let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
    
    
    
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.loadTodaysGames()
    
        }
    
            func loadTodaysGames(){
        print("load Games")
        let todaysGamesDatatask = URLSession.shared.dataTask(with: todaysGamesURL, completionHandler: dataLoaded)
        todaysGamesDatatask.resume()
    }
    func dataLoaded(data:Data?,response:URLResponse?,error:Error?){
        if let detailData = data {
            if  let inital = try? Initial.init(data: detailData){
               print(inital.dates)
            }else{
                 // print("Initial")
            }
        }else{
            print(error!)
        }
    }
    
    }
    
    0 讨论(0)
提交回复
热议问题