iOS & Swift 공부 - Parsing JSON

김영채 (Kevin)·2020년 12월 30일
0

iOS & Swift

목록 보기
4/107
post-thumbnail

친구와 간단한 Todo 앱을 만들기로 했다. 친구는 백엔드를 맡고, 나는 전반적인 iOS 개발을 맡기로 했는데, 내가 완전 초짜다 보니까 모든 것을 유튜브를 보면서 진행해야 했다.

Todo 앱을 만들고 싶으면 DB와 통신이 되어야하고, 각종 정보 (ex. 할일, description, 날짜 등) 를 JSON object 로 받아 스위프트로 처리해야 하는데, 이걸 할 줄 몰라 강의를 찾아봤다.

다행히 CodeWithChris 라는 유튜버가 친절하게 설명을 해주어 차근차근 따라해 볼 수 있었다.

우선 newsapi.org 이라는 곳의 API를 이용하여 연습해봤다.
사진 아래에 링크가 있는데, 이것을 미리 복사해둔다.

아래로 조금 스크롤을 하다보면 사진과 같이 JSON 데이터가 있는 것을 볼 수 있다. status, totalResults, articles, 그리고 articles 내에는 다시 여러가지의 데이터가 nested 되어 있는 것을 볼 수 있다.

스위프트에서 JSON 데이터를 파싱하려면 우선 맵핑하고자 하는 데이터를 구조체로 선언해줘야 한다.

임의로 NewsFeed.swift 라는 파일을 별도로 프로젝트 내에 생성을 한다.
구조체는 원래 선언하는 방법대로 선언하지만, 대신 Codable 이라는 프로토콜을 사용해야 한다. 아직 잘은 모르겠지만, JSON 데이터를 편리하게 디코딩 하려면 사용하는 것이 좋단다.

struct NewsFeed: Codable{
	var status : String = ""
    	var totalResults : Int = 0
    	var articles:[Article]?
}

일단 위와 같이 구조체를 선언한다. 0과 같이 초기값을 줘도 되고, 옵셔널 변수로 설정해줘도 무방한 것 같다.

특이한 점은, var articles:[Article]? 을 작성한 것처럼 배열 안에 Article 타입을 따로 정해줬다. 이는 아래를 보면 이해하기 조금 쉬울 것이다.

사진에서 보다시피 articles 키 안에 또 수많은 JSON 데이터 (Key-Value Pairs) 가 저장되어 있다.

이러한 데이터를 맵핑하기 위해서는 또 다른 스위프트 파일을 만들어줘야 한다.

Article.swift 라는 파일을 만들었다. 여기서는 대략적으로 위 사진과 같이 구조체를 선언해야 한다. 마찬가지로 Codable 이라는 프로토콜을 사용해야 한단다. (옵셔널 변수로 설정하였다)

struct Article: Codable{
    
    var author:String?
    var title:String?
    var description:String?
    var url:String?
    var urlToImage:String?
    var publishedAt:String?
    var content:String?
    
}

다음은 ViewController.swift 파일이다.

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        //Hit the API endpoint
        let urlString = "http://newsapi.org/v2/everything?q=bitcoin&from=2020-11-29&sortBy=publishedAt&apiKey=ad476a2319b24e7191a7d845537b9f1f"
        
        //turning the string into a URL object
        //URL() may return a nil, so we need a guard statement so it doesn't
        let url = URL(string: urlString)
        
        guard url != nil else{
            return
        }
        
        let session = URLSession.shared
        
        let dataTask = session.dataTask(with: url!) { (data,response,error) in
            
            //Check that there are no errors and that data exists
            if error == nil && data != nil {
                
                //Parse JSON
                let decoder = JSONDecoder()
                
                do{
                 
                    let newsFeed = try decoder.decode(NewsFeed.self, from: data!)
                
                    print(newsFeed)
                }
                catch{
                    print("Error in JSON parsing")
                }
            }
            
        }
        
        //Make the API Call
        dataTask.resume()
        
    }


}

대략적인 코드는 위와 같다.

 let urlString = "http://newsapi.org/v2/everything?q=bitcoin&from=2020-11-29&sortBy=publishedAt&apiKey=ad476a2319b24e7191a7d845537b9f1f"
 let url = URL(string: urlString)

url 객체를 생성하는 코드다.

let dataTask = session.dataTask(with: url!) { (data,response,error) in
            
            //Check that there are no errors and that data exists
            if error == nil && data != nil {
                
                //Parse JSON
                let decoder = JSONDecoder()
                
                do{
                 
                    let newsFeed = try decoder.decode(NewsFeed.self, from: data!)
                
                    print(newsFeed)
                }
                catch{
                    print("Error in JSON parsing")
                }
            }
            
        }

아직 초보자인 내가 이 부분을 정확히 이해하지 못했는데, 어찌됐든 JSONDecoder 를 이용해서 파싱이 정상적으로 가능하다고 배웠다.
decoder 라는 변수가 이를 이용하게끔 하고, 앞서 정의한 NewsFeed.swift 파일을 이용해서 디코딩을 하게 정의한다.

이 상태에서 print(newsFeed) 부분에 breakpoint 를 걸어 콘솔창에 po newsFeed 라고 치면, 아래와 같은 정보들이 쫙 뜨게된다.

왼쪽에서 보다시피 data, response 등의 정보들에 값들이 정상적으로 할당된 것이 확인된다. 우측에는 JSON 데이터가 파싱이 된 것을 확인할 수 있다.

일단 오늘은 가져온 데이터를 저런 식으로 확인하는 것 까지만 공부하였고, 추가로 가져온 정보를 실제 앱에서 쓸 수 있는 방법까지 배우려고 한다. 더 자세한 설명은 이후 포스팅에서 이어가겠다.

profile
맛있는 iOS 프로그래밍

0개의 댓글