📱 App Development Study/iOS🍎

[Udemy iOS & Swift Bootcamp] API 로 Json 데이터 받아오기. Json Parsing

ibelieveinme 2023. 5. 6. 17:36
728x90

* Json 이란?

: JavaScript Object Notation. 자바스크립트 객체 표기법.

: JavaScript 객체를 전송하기 쉽도록 가볍게 표현한 방법.

-> Networking을 위해 객체를 Json으로 변경하여 넘겨야 하고, Web에서 받아온 Json 데이터를 객체로 변경하는 Parse 함수가 필요하다.

 

[Json 데이터]

{
  "coord": {
    "lon": -0.1257,
    "lat": 51.5085
  },
  "weather": [
    {
      "id": 804,
      "main": "Clouds",
      "description": "overcast clouds",
      "icon": "04d"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 285.22,
    "feels_like": 284.91,
    "temp_min": 284.12,
    "temp_max": 286.13,
    "pressure": 1015,
    "humidity": 93
  },
  "visibility": 10000,
  "wind": {
    "speed": 2.06,
    "deg": 90
  },
  "clouds": {
    "all": 100
  },
  "dt": 1683354927,
  "sys": {
    "type": 2,
    "id": 2019646,
    "country": "GB",
    "sunrise": 1683347034,
    "sunset": 1683401420
  },
  "timezone": 3600,
  "id": 2643743,
  "name": "London",
  "cod": 200
}

 

* Networking 절차

1. 접근할 URL 선언

2. URL Session 선언

3. URL Session에게 task 주기

4. task 시작

 

Json 데이터 받아오기

Json Decoder로 Json 데이터를 객체로 변경하여 저장 & 사용하기

 

 

* 적용 코드

import Foundation

struct WeatherManager{
    
    let weatherURL = "https://api.openweathermap.org/data/2.5/weather?appid=7722c26a2cee69ed24d77d3f57d3daf3&units=metrics"
    
    func fetchWeather(cityName: String){
        let urlString = "\(weatherURL)&q=\(cityName)"
        performRequest(urlString: urlString)
    }
    
    func performRequest(urlString: String){
        //1. Create a URL
        if let url = URL(string: urlString){
            
            //2. Create a URLSession
            let session = URLSession(configuration: .default)
            
            //3. Give the session a task
            let task = session.dataTask(with: url){ (data, response, error) in
                if error != nil {
                    print(error!)
                    return
                }
                if let safeData = data {
                    self.parseJson(weatherData: safeData)
                }
            }
            
            //4. Start the task
            task.resume()
        }
    }
    
    func parseJson(weatherData: Data){
        let decoder = JSONDecoder()
        do{
            let decodedData = try decoder.decode(WeatherData.self, from: weatherData)
            print(decodedData.weather[0].id)
        } catch{
            print(error)
        }
    }
}

 

func performRequest(urlString: String){

     //url 이 있으면 if문 실행

     if let url = URL(string urlString){

         //URLSession에 .default 기본 옵션 적용해서 URLSession 객체 생성.

          let session = URLSession(configuration: .default)

         //URLSession에 task 주기. completionHandler 는 Closure로 표현. 

          let task = session.dataTask(wth: url) { (data, response, error) in

             //error 가 있으면 error 출력하고 return

              if error != nil {

                 print(error!)

                 return

             }

             //받은 data 사용

              if let safeData = data {

                 // data 를 객체로 바꿀 parse함수 호출

                 // Closure 내에서 함수를 호출할 경우 self 키워드를 써줘야 한다.

                 self.parseJson(weatherData: safeData)

            }

          }

         //task 시작

          task.resume()

     }

}

 

func parseJson(weatherData: Data){

    //JsonDecoder 호출

     let decoder = JSONDecoder()

     do {

            //weatherData를 WeatherData 형으로 변경

            // decode 중에 에러가 발생될 수 있으므로 반드시 try catch 문으로 에러처리를 해줘야 한다

            // try 구문에서 에러가 나면 그 밑줄은 실행되지 않고 바로 catch 문을 실행한다.

            let decodedData = try decoder.decode(WeatherData.self, from: weatherData)

            // weather 이 배열이니까 배열로 접근해야 함

             print(decodedData.weather[0].id)

     } catch {

            print(error)

     }

}

 

참고) URLSesson.dataTask

func dataTask(with: URL, completionHandler: (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask

URLSession으로 받아온 Data를 처리하고 싶으면 completionHandler가 있는 위 구문을 사용해야 한다.

URLSession.dataTask 함수는 URLSessionDataTask를 반환한다.

 

자세한 내용은 아래 공식문서 참고.

 

dataTask(with:completionHandler:) | Apple Developer Documentation

Creates a task that retrieves the contents of a URL based on the specified URL request object, and calls a handler upon completion.

developer.apple.com

 

import Foundation

struct WeatherData: Decodable{
    let name: String
    let weather: [Weather]
    let main: Main
}


struct Weather: Decodable{
    let id: Int
    let main: String
    let description: String
    let icon: String
}

struct Main: Decodable{
    let temp: Double
    
}

json -> 객체로 바꾸기 위한 데이터 구조 코드

Decodable 상속 필요. json 데이터 key와 이름이 같아야 함!

Weather 이 배열형이라  [Weather] 이렇게 표현해야 함.

 

참고) JsonDecoder

 

JSONDecoder | Apple Developer Documentation

An object that decodes instances of a data type from JSON objects.

developer.apple.com


참고로 [boringssl] boringssl_metrics_log_metric_block_invoke(151) Failed to log metrics 에러가 난다면 아래 순서로 환경변수 셋팅값을 추가해주면 된다.

 

  1. 화면 가온데 위 Product 클릭 > Edit Scheme 선택
  2. Run option 탭 > Arguments 진입 
  3. Environment Variables 에 아래 variable 추가
  4.  Name: OS_ACTIVITY_MODE, value: disable

728x90