Cannot read data from section "weather" of JSONDecoder file, got via Almofire

the data printed in console:

{"coord":{"lon":-0.13,"lat":51.51},"weather":[{"id":521,"main":"Rain","description":"shower rain","icon":"09d"}],"base":"stations","main":{"temp":289.64,"pressure":1006,"humidity":48,"temp_min":286.48,"temp_max":292.59},"visibility":10000,"wind":{"speed":1},"clouds":{"all":85},"dt":1558190870,"sys":{"type":1,"id":1414,"message":0.009,"country":"GB","sunrise":1558152298,"sunset":1558208948},"id":2643743,"name":"London","cod":200}

struct MyWeatherData: Codable {
    let coord : coord
    let weather : weather
}

struct coord: Codable {
    let lon: Double
    let lat: Double

}

struct weather: Codable {
    let array : [unknown] //here is my problem
    let base : String
}

struct unknown : Codable {
    let id : Int
    let main: String
    let description : String
    let icon : String
}


let cityLink = "https://api.openweathermap.org/data/2.5/weather?q=London"



        Alamofire.request(self.cityLink+"&APPID=\(self.myId)").responseJSON { (response) in
//            print("Request: \(String(describing: response.request))")   // original url request
//            print("Response: \(String(describing: response.response))")
//            print("Result: \(response.result)")

            if let data = response.data, let utf8 = String(data: data, encoding: .utf8) {

                print("Data is: \(utf8)")
                do {
                    let myData = try JSONDecoder().decode(MyWeatherData.self, from: data)
//                    print("lat is: \(myData.coord.lat)") //ok, working
                    print("weather is: \(myData.weather.main)") //not working

                } catch let myError {
                    print("error is: ", myError)
                }
            }


        }

3 Answers

0
vadian On Best Solutions

No, the problem is not here is my problem, the problem is in MyWeatherData.

Please read the JSON. It's very easy. The value for key weather is wrapped in [] so the object is an array.

And name all structs with uppercase letters to avoid confusion like let weather : weather

struct MyWeatherData : Decodable {
    let coord : Coord
    let weather : [Weather]
}

struct Coord : Decodable {
    let lon: Double
    let lat: Double
}

struct Weather : Decodable {
    let id : Int
    let main: String
    let description : String
    let icon : String
}
1
iDevid On

Please name your class/Models with first letter Capitalized.

The problem is that weather is an Array on MyWeatherData so it becomes:

struct MyWeatherData: Codable {
    let coord : Coord
    let weather : [Weather]
}

struct Coord: Codable {
    let lon: Double
    let lat: Double
}

struct Weather: Codable {
    let id : Int
    let main: String
    let description : String
    let icon : String
}
1
arkus On

In MyWeatherData the weather property should have [weather] type, as the JSON returns an array in weather key:

{
  "coord": {
    "lon": -0.13,
    "lat": 51.51
  },
  "weather": [{
    "id": 521,
    "main": "Rain",
    "description": "shower rain",
    "icon": "09d"
  }],
  "base": "stations",
  "main": {
    "temp": 289.64,
    "pressure": 1006,
    "humidity": 48,
    "temp_min": 286.48,
    "temp_max": 292.59
  },
  "visibility": 10000,
  "wind": {
    "speed": 1
  },
  "clouds": {
    "all": 85
  },
  "dt": 1558190870,
  "sys": {
    "type": 1,
    "id": 1414,
    "message": 0.009,
    "country": "GB",
    "sunrise": 1558152298,
    "sunset": 1558208948
  },
  "id": 2643743,
  "name": "London",
  "cod": 200
}

So your types should look like this:

struct MyWeatherData: Codable {
    let coord: coord
    let weather: [weather]
    let base: String
}

struct coord: Codable {
    let lon: Double
    let lat: Double
}

struct weather : Codable {
    let id : Int
    let main: String
    let description : String
    let icon : String
}

And then you can get weather instance by myWeatherData.weather.first