debugDescription: «Ожидается декодировать массив <Any>, но вместо этого найден словарь.», underError: nil) - PullRequest
0 голосов
/ 04 мая 2018

Я хочу загрузить онлайн-файл json в свое приложение, но я сталкиваюсь с этой ошибкой:

typeMismatch (Swift.Array, Swift.DecodingError.Context (codingPath: [], debugDescription: Msgstr "Предполагается декодировать массив, но вместо этого нашел словарь.", ringError: nil))

Я посмотрел на переполнение стека, но другие решения не помогли решить мои.

Мой JSON

Моя модель данных:

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
}

а вот мой viewcontroller

import UIKit

class TodaysGamesTableViewController: UITableViewController {
    var todaysGamesURL: URL = URL(string: "https://statsapi.web.nhl.com/api/v1/schedule")!

    var gameData: [Dates] = []
    let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)

    override func viewDidLoad() {
        super.viewDidLoad()
        loadTodaysGames()
    }

    func loadTodaysGames(){
        print("load Games")

        view.addSubview(activityIndicator)
        activityIndicator.frame = view.bounds
        activityIndicator.startAnimating()

        let todaysGamesDatatask = URLSession.shared.dataTask(with: todaysGamesURL, completionHandler: dataLoaded)

        todaysGamesDatatask.resume()
    }

    func dataLoaded(data:Data?,response:URLResponse?,error:Error?){
        if let detailData = data{
            print("detaildata", detailData)
            let decoder = JSONDecoder()
            do {
                let jsondata = try decoder.decode([Dates].self, from: detailData)
                gameData = jsondata //Hier .instantie wil doen krijg ik ook een error

                DispatchQueue.main.async{
                    self.tableView.reloadData()
                }
            }catch let error{
                print(error)
            }
        }else{
            print(error!)
        }
    }

Ответы [ 3 ]

0 голосов
/ 04 мая 2018

Правильный ответ сделан ранее от моих двух друзей

но вы должны сделать это лучше, я предоставлю вам решение, чтобы сделать код более чистым, и предоставлю вам массив дат

вот ваша модель с кодируемым

   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)
    }

}

А вот и контроллер сделает решение более простым

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 голосов
/ 04 мая 2018

Пожалуйста, научитесь понимать сообщения об ошибках декодирования, они очень наглядны.

Ошибка говорит о том, что вы собираетесь декодировать массив, но фактическим объектом является словарь (целевая структура).

Сначала взгляните на начало 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",

Он начинается с {, который является словарем (массив [), но вы хотите декодировать массив ([Dates]), это несоответствие типов, на которое ссылается сообщение об ошибке.


Но это только половина решения. После изменения строки на try decoder.decode(Dates.self вы получите еще одну ошибку, в которой нет значения для ключа copyright.

Посмотрите еще раз на JSON и сравните ключи с членами структуры. Структура, члены которой соответствуют ключам JSON, равна Initial, и вы должны получить массив dates для заполнения gameData.

let jsondata = try decoder.decode(Initial.self, from: detailData)
gameData = jsondata.dates
0 голосов
/ 04 мая 2018

JSON представлен вашей Initial структурой, а не массивом Dates.

Изменение:

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

до:

let jsondata = try decoder.decode(Initial.self, from: detailData)
...