티스토리 뷰

지난 번에 요청한 JSON데이터 기억나시나요?

 

{
  "coord": {
    "lon": 126.9778,
    "lat": 37.5683
  },
  "weather": [
    {
      "id": 800,
      "main": "Clear",
      "description": "clear sky",
      "icon": "01d"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 265.08,
    "feels_like": 261.52,
    "temp_min": 264.38,
    "temp_max": 266.84,
    "pressure": 1028,
    "humidity": 27,
    "sea_level": 1028,
    "grnd_level": 1021
  },
  "visibility": 10000,
  "wind": {
    "speed": 1.86,
    "deg": 294,
    "gust": 3.83
  },
  "clouds": {
    "all": 0
  },
  "dt": 1642122122,
  "sys": {
    "type": 1,
    "id": 5509,
    "country": "KR",
    "sunrise": 1642113967,
    "sunset": 1642149322
  },
  "timezone": 32400,
  "id": 1835848,
  "name": "Seoul",
  "cod": 200
}

 

 

이 데이터를 바로 쓸 순 없겠져!!
내가 필요한 놈들만 쏙쏙 뽑아서 재구성해야 합니당


이번 시간에는 요청한 데이터를 내가 원하는 데이터로 바꿔볼 거에요!!


우선 프로젝트를 하나 만들구요.

가장 먼저는 각 레이블들의 레이아웃을 잡아줄게요!
저는 temp, feels_like, id, main만 나타내고 싶으니까, 4개의 레이블만 잡아줄게요.


이 부분은 간단하므로 더보기로 보시면 돼요!

더보기
더보기
class ViewController: UIViewController {

    let tempLbl = UILabel()
    let feelsLikeLbl = UILabel()
    let idLbl = UILabel()
    let mainLbl = UILabel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureUI()
        getWeather()
    }


}

//MARK: -UI
extension ViewController {
    final private func configureUI() {
        setAttributes()
        setConstraints()
    }
    final private func setAttributes() {
        tempLbl.text = "temp"
        feelsLikeLbl.text = "feels_Like"
        idLbl.text = "id"
        mainLbl.text = "main"
        
    }
    final private func setConstraints() {
        [tempLbl, feelsLikeLbl, idLbl, mainLbl].forEach {
            view.addSubview($0)
            $0.translatesAutoresizingMaskIntoConstraints = false
        }
        
        NSLayoutConstraint.activate([
            tempLbl.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),
            tempLbl.centerYAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor),
            
            feelsLikeLbl.topAnchor.constraint(equalTo: tempLbl.bottomAnchor, constant: 15),
            feelsLikeLbl.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),

            idLbl.topAnchor.constraint(equalTo: feelsLikeLbl.bottomAnchor, constant: 15),
            idLbl.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),

            mainLbl.topAnchor.constraint(equalTo: idLbl.bottomAnchor, constant: 15),
            mainLbl.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),
        ])
    }
}

 


그리고 command N을 눌러 swift 파일을 하나 추가해줍니다!
이름은 WeatherData.swift로 해줄게요롱이.


그리고 WeatherData라는 구조체를 하나 만들어줍니다.

import Foundation

struct WeatherData: Codable {

}



그리고 Decodable이라는 프로토콜을 채택해주는데요.
Decodable을 옵션키를 누른채로 보면 외부 표현(아마도 JSON데이터?)를 해독하는 프로토콜이라고 하네요.
받아온 JSON data를 parsing하기 위해서는 이 프로토콜을 채택해야만 해요.

 

받아온 데이터를 보면 main 안에 있는 temp, feels_like / weather 안에 있는 id, main을 사용할 거에요.

"main": { 
    "temp": 1.1, 
    "feels_like": -0.56, 
    "temp_min": -0.77, 
    "temp_max": 1.78, 
    "pressure": 1021, 
    "humidity": 52 
}



우선 main부터 볼게요. main의 값인 temp와 feels_like를 이용하기 위해서는 Weather 구조체 안에 또 Main이라는 구조체를 만들어 줍니다. 그리고 main 상수 선언하고 이 Main타입으로 만들어줘요.
+ Main 구조체 또한 Decodable 프로토콜을 채택해야 해요!!

struct WeatherData: Decodable { 
    let main: Main 
    
    struct Main: Decodable {
    	let temp, feelsLike, tempMin, tempMax: Double 
        let pressure, humidity: Int 
    }
}

이렇게 하면 main.temp를 통해 temp, feels_like 등과 같이 main의 속한 값들을 모두 사용할 수 있겠져?

 



근데!! 여기서 혹시 이상한 거 느껴지시나요? JSON 데이터에서는 feels_like였던 값이 여기에는 feelsLike로 바뀌어 있거든여!! 왓더!!


바로 CodingKey를 사용했기 때문인데여! swift에서는 'feels_like'보다는 'feelLike'가 익숙하잖아요? 이렇게 바꿀 수 있게 도와주는 것이 바로 CodingKey입니다!


CodingKey는 프로토콜이구요. 열거형으로 선언합니다.
사용하는 방법은 간단해여. 각 케이스에 내가 원하는 값을 원시값으로 설정해주면 됩니다요.
그러면 이제부터 feels_like를 우리가 익숙한 feelsLike로 사용할 수 있어여 ㅎㅎㅎ
실수할 일이 줄어들겠져?

struct WeatherData: Decodable {

	let main: Main 
    
	struct Main: Decodable { 
        let temp, feelsLike, tempMin, tempMax: Double 
        let pressure, humidity: Int 

		//CodingKey 
        enum CodingKeys: String, CodingKey { 
            case temp 
            case feelsLike = "feels_like" 
            case tempMin = "temp_min" 
            case tempMax = "temp_max" 
            case pressure, humidity 
        } 
    } 
}

 


 

이제 weather 상수를 만들어볼게욧
weather같은 형태가 실수하기 쉬운 형태라고 해요.

 "weather": [ 
 	{ 
        "id": 615, 
        "main": "Snow", 
        "description": "light rain and snow", 
        "icon": "13n"
     } 
]

아래 main과의 차이가 느껴지시나여? (저는 못 느꼈음 ㅎㅎ)

"main": { 
    "temp": 1.1, 
    "feels_like": -0.56, 
    "temp_min": -0.77, 
    "temp_max": 1.78, 
    "pressure": 1021, 
    "humidity": 52 
}

 

weather는 [ ]에 한 번 더 감싸져있져?
main의 형태 -> [main: 값]
weather의 형태 -> [weather: [키:값]]

그렇기 때문에 상수 weather는 구조체 Weather타입이 아닌, [Weather] 타입이에요.

struct WeatherData: Codable {
    let main: Main
    let weather: [Weather]
    
    struct Main: Codable {
        let temp, feelsLike, tempMin, tempMax: Double
        let pressure, humidity: Int
        
        
        enum CodingKeys: String, CodingKey {
            case temp
            case feelsLike = "feels_like"
            case tempMin = "temp_min"
            case tempMax = "temp_max"
            case pressure, humidity
        }
    }
    
    struct Weather: Codable {
        let id: Int
        let main, weatherDescription, icon: String
        
        enum CodingKeys: String, CodingKey {
            case id, main
            case weatherDescription = "description"
            case icon
        }
    }
}

 

그리고 Weather 구조체에서도 CodingKey 프로토콜을 채택해줄게요.


처음에는 JSON 형태만 봐도 머리가 아팠는데, 이렇게 다시 구조체로 만들어보니 알거 같기도 하고?
그래도 역시나 잘못된 것이 있다면 알려주십셔 슨배님덜!

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크