debugDescription:“预期解码 Array<Any>,但找到了字典。”,underlyingError:nil)
Posted
技术标签:
【中文标题】debugDescription:“预期解码 Array<Any>,但找到了字典。”,underlyingError:nil)【英文标题】:debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil) 【发布时间】:2018-10-15 05:40:10 【问题描述】:我想将一个在线 json 文件加载到我的应用程序中,但我遇到了这个错误:
typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "预期解码 Array 但找到了字典。", 底层错误:无))
我查看了 ***,但其他解决方案无助于解决我的问题。
我的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!)
【问题讨论】:
你的错误到底发生在哪里? 发生在:let jsondata = try decoder.decode([Dates].self, from: detailData)。 【参考方案1】: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!)
【讨论】:
将所有内容示意性地、粗心地声明为可选和使用try?
忽略解码错误是非常糟糕的建议。
好的,我的答案已根据您的笔记更新,感谢@vadian,感谢您提供更多笔记【参考方案3】:
请学会理解解码错误信息,它们非常具有描述性。
错误提示您要解码一个数组,但实际对象是一个字典(目标结构)。
先看一下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
【讨论】:
感谢您帮助我!我现在遇到了一些 keyNotFound 错误,但我会尝试自己修复它们!我对 swift 比较陌生,所以欢迎任何帮助!再次感谢!以上是关于debugDescription:“预期解码 Array<Any>,但找到了字典。”,underlyingError:nil)的主要内容,如果未能解决你的问题,请参考以下文章
XCUIApplication().debugDescription 的打印输出正在崩溃 UIAutomated Test XCode 8