1

有人可以告诉这里有什么问题吗?

它向我发送此错误:类型“CityWeatherInfo”不符合协议“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是这样的:

{"coord":{"lon":-0.13,"lat":51.51},"weather":[{"id":804,"main":"Clouds","description":"阴云"," icon":"04n"}],"base":"stations","main":{"temp":287.45,"feels_like":286.61,"temp_min":284.82,"temp_max":289.15,"pressure": 1012,"湿度":72},"能见度":10000,"风":{"速度":1,"度":0},"云":{"全部":100},"dt":1592362322 ,"sys":{"type":1,"id":1414,"country":"GB","sunrise":1592365362,"sunset":1592425222},"timezone":3600,"id":2643743 ,"名称":"伦敦","鳕鱼":200}

4

1 回答 1

2

如果结构或类采用Codable所需的方法init(from decoder: Decoder)encode(to encoder: Encoder)默认合成。

但是,如果您自己实现其中一种方法,那么您也必须实现另一种方法。或者——在这种情况下——仅仅Decodable因为你只是在读取/解码数据而采用。

您的代码中有一些不好的做法。

  • 自定义 CodingKeysWeatherKeysMainKeys是没有意义的,因为在默认语法中,框架会生成名为CodingKeys. 自定义键仅在自定义实现中被考虑。

  • 两者nestedContainers都不需要,如果它们由相同的 CodingKeys 键入,它们无论如何都没有意义。

  • 如果字典键与结构成员名称匹配,则可以省略 CodingKeys。

  • 如果结构成员的值不会被修改,则将它们声明为常量 ( let)。

  • 根据命名约定,变量应该被命名为lowerCamelCased将snake_case转换为camelCase的一种便捷方法是指定convertFromSnakeCase密钥解码策略。


API通过openweathermap添加 URL 来提供摄氏度units=metric或华氏度通过添加units=imperial. 例如

https://api.openweathermap.org/data/2.5/weather?q=London&units=metric&appid=•••••••••••••"

UNIX 时间戳 (1592362322) 可以Date通过指定secondsSince1970日期解码策略来解码

可以以这种简单的形式创建结构

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
}

并使用此代码解码数据

 do {
     let decoder = JSONDecoder()
     decoder.keyDecodingStrategy = .convertFromSnakeCase
     decoder.dateDecodingStrategy = .secondsSince1970
     let weatherInfo = try decoder.decode(CityWeatherInfo.self, from: data)
     print(weatherInfo)
 } catch {
    print(error)
 }
于 2020-06-17T17:10:52.503 回答