Can someone tell what's wrong here please?
It send me this error: Type 'CityWeatherInfo' does not conform to protocol 'Encodable'
struct CityWeatherInfo: Codable {
   var name: String
   var main: Main
   var weathers: [Weather]
   private enum CodingKeys: String, CodingKey {
       case weathers = "weather"
       case main = "main"
       case name
   }
   init(from decoder: Decoder) throws {
       let container = try decoder.container(keyedBy: CodingKeys.self)
       self.name = try container.decode(String.self, forKey: .name)
       let mainContainer = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .main)
       let weatherContainer = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .weathers)
   }
}
struct Weather: Decodable {
   var main: String
   var description: String
   private enum WeatherKeys: String, CodingKey {
       case main = "main"
       case description = "description"
   }
}
struct Main: Decodable {
   var temp: Double
   var feels_like: Double
   var temp_min: Double
   var temp_max: Double
   private enum MainKeys: String, CodingKey {
       case temp = "temp"
       case feels_like = "feels_like"
       case temp_min = "temp_min"
       case temo_max = "temp_max"
   }
}
Json is this:
{"coord":{"lon":-0.13,"lat":51.51},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04n"}],"base":"stations","main":{"temp":287.45,"feels_like":286.61,"temp_min":284.82,"temp_max":289.15,"pressure":1012,"humidity":72},"visibility":10000,"wind":{"speed":1,"deg":0},"clouds":{"all":100},"dt":1592362322,"sys":{"type":1,"id":1414,"country":"GB","sunrise":1592365362,"sunset":1592425222},"timezone":3600,"id":2643743,"name":"London","cod":200}
If a struct or class adopts Codable the required methods init(from decoder: Decoder) and encode(to encoder: Encoder) are synthesized by default.
But if you implement one of the methods yourself you have to implement the other, too. Or – in this case – adopt only Decodable because you are only reading/decoding the data.
There are a few bad practices in your code.
The custom CodingKeys WeatherKeys and MainKeys are pointless because in the default syntax the framework generates the keys named CodingKeys. Custom keys are considered only in a custom implementation.
Both nestedContainers are not needed and they make no sense anyway if they are keyed by the same CodingKeys.
You can omit the CodingKeys if the dictionary keys match the struct member names.
If the values of the struct members are not going to be modified declare them as constants (let).
According to the naming convention variables are supposed to be named lowerCamelCased. A convenient way to translate snake_case to camelCase is to specify the convertFromSnakeCase key decoding strategy.
The openweathermap API provides degrees in Celsius by adding units=metric in the URL or Fahrenheit by adding units=imperial. For example
https://api.openweathermap.org/data/2.5/weather?q=London&units=metric&appid=•••••••••••••"
The UNIX timestamps (1592362322) can be decoded as Date by specifying the secondsSince1970 date decoding strategy
The structs can be created in this simple form
struct CityWeatherInfo: Decodable {
   let name: String
   let main: Main
   let weather: [Weather]
   let dt : Date
}
struct Weather: Decodable {
   let main: String
   let description: String
}
struct Main: Decodable {
   let temp, tempMin, tempMax, feelsLike : Double
}
And decode the data with this code
 do {
     let decoder = JSONDecoder()
     decoder.keyDecodingStrategy = .convertFromSnakeCase
     decoder.dateDecodingStrategy = .secondsSince1970
     let weatherInfo = try decoder.decode(CityWeatherInfo.self, from: data)
     print(weatherInfo)
 } catch {
    print(error)
 }
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With