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)
}
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.