オンラインのjsonファイルをアプリケーションにロードしたいのですが、次のエラーが発生します。
typeMismatch(Swift.Array、Swift.DecodingError.Context(codingPath:[]、debugDescription: "配列をデコードする予定ですが、代わりに辞書が見つかりました。"、underlyingError:nil))
私はstackoverflowを調べましたが、他の解決策は私の解決に役立ちませんでした。
私の 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
}
これが私のビューコントローラーです
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!)
}
}
デコードエラーメッセージを理解することを学んでください、それらは非常に説明的です。
エラーは、配列をデコードしようとしているが、実際のオブジェクトは辞書(ターゲット構造体)であることを示しています。
まず、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
JSONは、Initial
の配列ではなく、Dates
構造体で表されます。
変化する:
let jsondata = try decoder.decode([Dates].self, from: detailData)
に:
let jsondata = try decoder.decode(Initial.self, from: detailData)
正解は私の2人の友人から以前に行われました
しかし、あなたはそれをより良くしなければなりません私はあなたがコードをよりきれいにするための解決策を提供し、あなたに日付の配列を与えます
これがコード化可能なモデルです
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!)
}
}
}