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

xctest debugDescription 显示以元素为根的部分后代

iOS description

如何区分错误码?

数据映射问题

类型不匹配 Swift JSON