2017-08-21 9 views
3

私はもう一度Swift 4 Codableで遊んでいますが、私がハングアップしていると思ったときに、私はこの問題を応答からWeatherキーをデコードすることで得ています。Swift4で配列をデコードするCodable

let jsonData = """ 
    {"coord":{"lon":-113,"lat":35}, 
"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}], 
"base":"stations", 
"main":{"temp":291.15,"pressure":1022,"humidity":72,"temp_min":291.15,"temp_max":291.15}, 
"visibility":16093,"wind":{"speed":3.6,"deg":200}, 
"clouds":{"all":1}, 
"dt":1503294780,"sys":{"type":1,"id":321,"message":0.184,"country":"US","sunrise":1503320222,"sunset":1503367937}, 
"id":5308281,"name":"Paulden","cod":200} 
""" 

スウィフトモデル:

//Top Level Container 
struct Response: Codable { 

    enum ResponseKeys: String, CodingKey { 
     case name 
     case code = "cod" 
     case main 
     case weather 
    } 
    //Nested Level Keys: Response > Weather 
    enum WeatherKeys: String, CodingKey { 
     case weather 
    } 
    //Nested Level Keys: Response > Main 
    enum MainKeys: String, CodingKey { 
     case temp 
     case pressure 
     case humidity 
     case tempMin = "temp_min" 
     case tempMax = "temp_max" 
    } 
    //Properties 
    var name: String 
    var code: Int 
    var temp: Double 
    var pressure: Int 
    var weather:[WeatherObj] 

    //Custom Init 
    init(from decoder: Decoder) throws { 
     let container = try decoder.container(keyedBy: ResponseKeys.self) 
     let weatherContainer = try container.nestedContainer(keyedBy: WeatherKeys.self, forKey: .weather) 
     let mainContainer = try container.nestedContainer(keyedBy: MainKeys.self, forKey: .main) 
     self.name = try container.decode(String.self, forKey: .name) 
     self.code = try container.decode(Int.self, forKey: .code) 
     self.pressure = try mainContainer.decode(Int.self, forKey: .pressure) 
     self.temp = try mainContainer.decode(Double.self, forKey: .temp) 

     // Here is where it throws: the data couldn’t be read because it isn’t in the correct format 
     self.weather = try weatherContainer.decode([WeatherObj].self, forKey: .weather) 
    } 
} 

私は正しくやっていないよ何かわかりません。他のすべてが自分のモデルに完全にデコードします。配列をデコードするときだけです。助言がありますか?

答えて

2

weatherキーを正しくデコードしました。これはトップレベルのキーなので、サブコンテナを作成する必要はありません。これは十分です:

self.weather = try container.decode([WeatherObj].self, forKey: .weather) 

私は実際にあなたが復号処理を容易にするためにJSONに非常に近いままprivate structを作成することをお勧めしますが。次に、データモデルを初期化する部分を取り除くことができます:

struct Response: Codable { 
    var name: String 
    var code: Int 
    var temp: Double 
    var pressure: Int 
    var weather: [WeatherObj] 

    // This stays as close to the JSON as possible to minimize the amount of manual code 
    // It uses snake_case and the JSON's spelling of "cod" for "code". Since it's private, 
    // outside caller can never access it 
    private struct RawResponse: Codable { 
     var name: String 
     var cod: Int 
     var main: Main 
     var weather: [WeatherObj] 

     struct Main: Codable { 
      var temp: Double 
      var pressure: Int 
     } 
    } 

    init(from decoder: Decoder) throws { 
     let rawResponse = try RawResponse(from: decoder) 

     // Now pick the pieces you want 
     self.name  = rawResponse.name 
     self.code  = rawResponse.cod 
     self.temp  = rawResponse.main.temp 
     self.pressure = rawResponse.main.pressure 
     self.weather = rawResponse.weather 
    } 
} 
関連する問題