You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 4中使用SwiftyJSON解析NBA赛事统计JSON数据求助

Fixing SwiftyJSON Parsing for NBA Standings API in Swift 4

Hey there! Let's get your NBA standings parsing sorted out. The main issue with your current code is that you're not navigating the actual structure of the NBA API's JSON response correctly—let's walk through this step by step.

First, Understand the API's JSON Structure

The NBA standings API returns a resultSets array, where each entry contains:

  • headers: An array of string labels for each data field (like "TeamName", "WINS", "LOSSES", "WIN_PCT")
  • rowSet: An array of arrays, where each inner array represents a single team's stats (ordered to match the headers list)

You can't directly access json["Warriors"] because the team data isn't stored under a named key—it's in the rowSet array entries.

Working Code Implementation

Here's a corrected version that finds the Golden State Warriors and extracts their key stats:

import SwiftyJSON

// Note: Using Data(contentsOf:) is synchronous and will block the main thread.
// For production code, use URLSession's async request (example below)
let urlString = "http://stats.nba.com/stats/leaguestandingsv3?LeagueID=00&Season=2017-18&SeasonType=Regular+Season"
guard let url = URL(string: urlString) else {
    print("Invalid URL provided")
    return
}

do {
    let nbaData = try Data(contentsOf: url)
    let json = try JSON(data: nbaData)
    
    // Grab the first result set (this contains the regular season standings data)
    guard let standingsResultSet = json["resultSets"].array?.first else {
        print("No standings data found in the response")
        return
    }
    
    // Extract headers to map field names to their index in the row arrays
    let statHeaders = standingsResultSet["headers"].arrayValue.map { $0.stringValue }
    // Extract all team data rows
    let teamRows = standingsResultSet["rowSet"].arrayValue
    
    // Loop through rows to find the Golden State Warriors
    for teamRow in teamRows {
        // Locate the "TeamName" field index and check if it's the Warriors
        guard let teamNameIndex = statHeaders.firstIndex(of: "TeamName"),
              let teamName = teamRow[teamNameIndex].string,
              teamName == "Golden State Warriors" else {
            continue
        }
        
        // Get indices for the stats we want
        let winIndex = statHeaders.firstIndex(of: "WINS")!
        let lossIndex = statHeaders.firstIndex(of: "LOSSES")!
        let winPctIndex = statHeaders.firstIndex(of: "WIN_PCT")!
        let confRankIndex = statHeaders.firstIndex(of: "ConferenceRank")!
        
        // Extract the values
        let wins = teamRow[winIndex].intValue
        let losses = teamRow[lossIndex].intValue
        let winPercentage = teamRow[winPctIndex].doubleValue
        let conferenceRank = teamRow[confRankIndex].intValue
        
        // Print or use the stats
        print("Golden State Warriors 2017-18 Regular Season Stats:")
        print("Conference Rank: \(conferenceRank)")
        print("Wins: \(wins) | Losses: \(losses)")
        print("Win Percentage: \(String(format: "%.3f", winPercentage))")
        
        // Exit loop once we find the Warriors
        break
    }
    
} catch {
    print("Error handling data: \(error.localizedDescription)")
}

Better Practice: Asynchronous Network Request

Using Data(contentsOf:) blocks the main thread, which is bad for user experience. Here's how to do it asynchronously with URLSession:

import SwiftyJSON

let urlString = "http://stats.nba.com/stats/leaguestandingsv3?LeagueID=00&Season=2017-18&SeasonType=Regular+Season"
guard let url = URL(string: urlString) else {
    print("Invalid URL")
    return
}

URLSession.shared.dataTask(with: url) { data, response, error in
    guard let data = data, error == nil else {
        print(error?.localizedDescription ?? "Unknown network error")
        return
    }
    
    do {
        let json = try JSON(data: data)
        // Reuse the parsing logic from the synchronous example here
        guard let standingsResultSet = json["resultSets"].array?.first else {
            print("No standings data found")
            return
        }
        
        let statHeaders = standingsResultSet["headers"].arrayValue.map { $0.stringValue }
        let teamRows = standingsResultSet["rowSet"].arrayValue
        
        for teamRow in teamRows {
            guard let teamNameIndex = statHeaders.firstIndex(of: "TeamName"),
                  let teamName = teamRow[teamNameIndex].string,
                  teamName == "Golden State Warriors" else {
                continue
            }
            
            let winIndex = statHeaders.firstIndex(of: "WINS")!
            let lossIndex = statHeaders.firstIndex(of: "LOSSES")!
            let winPctIndex = statHeaders.firstIndex(of: "WIN_PCT")!
            
            let wins = teamRow[winIndex].intValue
            let losses = teamRow[lossIndex].intValue
            let winPct = teamRow[winPctIndex].doubleValue
            
            print("Warriors Stats (Async):")
            print("Wins: \(wins), Losses: \(losses), Win %: \(winPct)")
            break
        }
        
    } catch {
        print("Parsing error: \(error.localizedDescription)")
    }
}.resume()

Key Notes

  • We use the headers array to find the index of each stat field—this makes the code resilient if the API changes the order of fields (as long as the field names stay the same)
  • The team name we check for is the full official name: "Golden State Warriors" (not just "Warriors")
  • Always handle optional values safely with guard to avoid crashes

*Your welcome stats analysts ;)

内容的提问来源于stack exchange,提问作者husharoonie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:49:32