简体   繁体   中英

Parsing JSON using Codable giving me nil - Swift

I am trying to parse JSON data. Here is the model:

struct WeeklyForecastResponse: Codable {
    var cod: String
    var message, cnt: Int
    var list: [List]
    var city: City


// MARK: - City
struct City: Codable {
    var id: Int
    var name: String
    var coord: Coord
    var country: String
    var population, timezone, sunrise, sunset: Int
}

// MARK: - Coord
struct Coord: Codable {
    var lat, lon: Double
}

// MARK: - List
struct List: Codable {
    var dt: Int
    var main: MainClass
    var weather: [Weather]
    var clouds: Clouds
    var wind: Wind
    var sys: Sys
    var dtTxt: String
    var snow, rain: Rain?

    enum CodingKeys: String, CodingKey {
        case dt, main, weather, clouds, wind, sys
        case dtTxt = "dt_txt"
        case snow, rain
    }
}

// MARK: - Clouds
struct Clouds: Codable {
    var all: Int
}

// MARK: - MainClass
struct MainClass: Codable {
    var temp, tempMin, tempMax: Double
    var pressure, seaLevel, grndLevel, humidity: Int
    var tempKf: Double

    enum CodingKeys: String, CodingKey {
        case temp
        case tempMin = "temp_min"
        case tempMax = "temp_max"
        case pressure
        case seaLevel = "sea_level"
        case grndLevel = "grnd_level"
        case humidity
        case tempKf = "temp_kf"
    }
}

// MARK: - Rain
struct Rain: Codable {
    var the3H: Double

    enum CodingKeys: String, CodingKey {
        case the3H = "3h"
    }
}

// MARK: - Sys
struct Sys: Codable {
    var pod: Pod
}

enum Pod: String, Codable {
    case d = "d"
    case n = "n"
}



// MARK: - Weather
struct Weather: Codable {
    var id: Int
    var main: MainEnum
    var weatherDescription, icon: String

    enum CodingKeys: String, CodingKey {
        case id, main
        case weatherDescription = "description"
        case icon
    }
}

enum MainEnum: String, Codable {
    case clear = "Clear"
    case clouds = "Clouds"
    case rain = "Rain"
    case snow = "Snow"
}

// MARK: - Wind
struct Wind: Codable {
    var speed: Double
    var deg: Int
}
}

The URL is api.openweathermap.org/data/2.5/forecast?lat=42.33&lon=-84.04&APPID=0729d39986bfdd23470f485457a04c6d&units=Imperial

And here is the actual parsing


            guard let url = URL(string: fullURL) else {
                print("Error getting the URL")
                return
            }
            URLSession.shared.dataTask(with: url) {
                (data, resp, err) in

                DispatchQueue.main.async {
                    do {
                        let decoder = JSONDecoder()
                        decoder.keyDecodingStrategy = .convertFromSnakeCase

                        let json = try decoder.decode(WeeklyForecastResponse.self, from: data!)

                        self.fiveDayWeatherData = [json]
                        self.temp = json.list[0].main.temp
                    }
                    catch {
                        print(error)
                    }
                }
            }.resume()

        }

I am getting this error: Fatal error: Unexpectedly found nil while unwrapping an Optional value: file. Anyone know why? I am pretty sure my model is correct, and the URL works properly. I get the error on the decode line.

You are force unwrapping data so its likely you don't have a real response. You should be handling and checking for the error first, then unwrapping the data. Are you sure you have arbitrary loads on for app transport security? because the URL you gave definitely returns data.

URLSession.shared.dataTask(with: url) { [weak self] (data, resp, err) in
  if let error = err {
    return print(error.localizedDescription)
  }
  guard let data = data else {
    return print("No data")
  }
  let decoder = JSONDecoder()
  decoder.keyDecodingStrategy = .convertFromSnakeCase
  switch Result(catching: { try decoder.decode(WeeklyForecastResponse.self, from: data) }) {
  case .success(let json):
    DispatchQueue.main.async { [weak self] in
      self?.fiveDayWeatherData = [json]
      self?.temp = json.list[0].main.temp
    }
  case .failure(let error):
    print(error.localizedDescription)
  }
}.resume()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM