0
votes

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

3 Answers

1
votes

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
votes

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
votes

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