Now wishing to rely on any third party libraries I shifted gear up to Swift 4 from v3 as passing JSON was specifically addressed. However, just trying it out with the OpenWeatherApp API found the catch error would always display?!
struct WeatherMain : Codable {
let humidity : Int?
let pressure : Int?
let temp : Float?
let tempMax : Float?
let tempMin : Float?
enum CodingKeys: String, CodingKey {
case humidity = "humidity"
case pressure = "pressure"
case temp = "temp"
case tempMax = "temp_max"
case tempMin = "temp_min"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
humidity = try values.decodeIfPresent(Int.self, forKey: .humidity)
pressure = try values.decodeIfPresent(Int.self, forKey: .pressure)
temp = try values.decodeIfPresent(Float.self, forKey: .temp)
tempMax = try values.decodeIfPresent(Float.self, forKey: .tempMax)
tempMin = try values.decodeIfPresent(Float.self, forKey: .tempMin)
}
}
class ViewController: UIViewController {
var weather = [WeatherMain]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let jsonURL = "http://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22"
let url = URL(string: jsonURL)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
do {
self.weather = try JSONDecoder().decode([WeatherMain].self, from: data!)
for weatherCondition in self.weather {
print(weatherCondition.humidity!)
}
}
catch {
print("Error")
}
}.resume()
}
The JSON response does not contain an array of WeatherMain, it contains a response dictionary with the weather info array stored under a weather key. This works for me:
struct Weather: Codable {
let humidity: Int?
let pressure: Int?
let temp: Float?
let tempMax: Float?
let tempMin: Float?
enum CodingKeys: String, CodingKey {
case humidity
case pressure
case temp
case tempMax = "temp_max"
case tempMin = "temp_min"
}
}
struct Response: Codable {
let weather: [Weather]
}
let dataURL = "http://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22"
do {
let data = try Data(contentsOf: URL(string: dataURL)!)
let weather = try JSONDecoder().decode(Response.self, from: data)
print(weather)
} catch {
print(error)
}
But it doesn’t. In fact it doesn’t even look the way I have written the model – it looks like what you want is stored as a dictionary under the main key:
I just spent the day with Ray Wenderlich learning about JSON and now the syntax makes a lot more sense.
It is true that the data I was after was under the "main" key in the dictionary, and it looks like you access that through the Response struct with the constant "main"?
I think, with the reference before as "weather" and not "main", the data would not match up when retrieved?