I want to load an online json file into my application, but I am running into this error:
typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array but found a dictionary instead.", underlyingError: nil))
I have looked on stackoverflow but other sollutions didn't help to solve mine.
My json
My datamodel:
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
}
and here is my 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!)
}
}
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
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With