Тип "" не соответствует протоколу "Кодируемый" - PullRequest
0 голосов
/ 17 июня 2020

Кто-нибудь может сказать, что здесь не так?

Мне прислали эту ошибку: Тип «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 это:

{"corrective": {"lon": - 0.13, "lat": 51.51}, "weather": [{"id": 804, "main": "Clouds", "description": "пасмурные облака", "icon": "04n"}], "base": "станции", "main": {"temp": 287.45, "feel_like": 286.61, "temp_min": 284.82, "temp_max": 289.15, «давление»: 1012, «влажность»: 72}, «видимость»: 10000, «ветер»: {«скорость»: 1, «градус»: 0}, «облака»: {«все»: 100} , «dt»: 1592362322, «sys»: {«type»: 1, «id»: 1414, «country»: «GB», «sunrise»: 1592365362, «sunset»: 1592425222}, «timezone»: 3600 , "id": 2643743, "name": "Лондон", "cod": 200}

1 Ответ

0 голосов
/ 17 июня 2020

Если структура или класс принимает Codable, необходимые методы init(from decoder: Decoder) и encode(to encoder: Encoder) синтезируются по умолчанию.

Но если вы реализуете один из методов самостоятельно, вам придется реализовать и другой . Или - в этом случае - используйте только Decodable, потому что вы только читаете / декодируете данные.

В вашем коде есть несколько плохих практик.

  • Пользовательские CodingKeys WeatherKeys и MainKeys бессмысленны, потому что в синтаксисе по умолчанию платформа генерирует ключи с именем CodingKeys. Пользовательские ключи учитываются только в специальной реализации.

  • Оба nestedContainers не нужны и в любом случае не имеют смысла, если они вводятся одними и теми же CodingKeys.

  • Вы можете опустить CodingKeys, если ключи словаря совпадают с именами элементов структуры.

  • Если значения элементов структуры не будут изменены, объявите их как константы (let).

  • В соответствии с соглашением об именах переменные должны иметь имена lowerCamelCased . Удобный способ перевести snake_case в camelCase - указать стратегию декодирования ключа convertFromSnakeCase.


The openweathermap API предоставляет градусы Цельсия, добавляя units=metric в URL-адрес, или градусы Фаренгейта, добавляя 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)
 }
...