본문 바로가기
Swfit

Swift JSON Parsing하기

by GGShin 2022. 3. 21.

저는 Parsing하는 과정을 좋아합니다. 예쁘게 잘 짜여진 API에서 원하는 자료를 꺼내오는 게 마치 보물을 찾아오는 것 같아요 ㅎㅎ

보통 JSON이 많이 사용이 되고 있기 때문에 JSON 형태일 때 어떻게 자료를 parsing 하는지 예시를 통해서 알아보겠습니다.

1) Array형태( [ ] )인 경우

jsonplaceholder에서 제공하는 api

위의 JSON은 상당히 단순한 형태입니다. 보시면 아시겠지만 userId, id, title, body 모두 같은 레벨에 있어서 여러 뎁스를 거치지 않아도 원하는 값을 가져올 수 있게 되어있습니다. 그리고 {userId, id, title, body}가 array 안에 들어가 있는 구조입니다. 

이 경우에는 data의 structure를 아래와 같이 잡아주면 끝입니다. 더 타고 들어갈 필요가 없기 때문에 한 번에 끝납니다. 

1
2
3
4
5
6
struct Data: Codable {
    let userId: Int
    let id: Int
    let title: String
    let body: String
}
cs

이렇게 Data structure를 만들어주고 parsing을 할 때는 아래처럼 [ ] 안에 Data가 담긴 형태로 parse하면 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
       guard let data = data else {
            return
        }
        
        do {
            //Data가 array안에 담겨있기 때문에 decode 시에 array 형태로 해주어야 합니다.
            let decodedData = try JSONDecoder().decode([Data].self, from: data)
            
            print(decodedData[0].title)
//[Data] array 0번째 요소의 title이 프린트 됩니다.
            
        } catch let jsonErr {
        print("Error serializing:", jsonErr)
    }
cs

2) { } 로 감싸져 있는 경우

이번에는 여러 뎁스를 들어가는 조금은 복잡한 JSON을 parsing 해보는 방법을 알아보겠습니다.

아래의 JSON의 경우 가장 큰 데이터 덩어리가 { } 안에 담겨있고 response 부터 시작해 여러 레벨에 거쳐 정보들이 들어있음을 알 수 있습니다.

단순하게 나타내면 이렇게 볼 수 있겠습니다.

상당히 복잡해보이지만, 겁먹지 말고 내가 원하는 정보가 어디에 있는지부터 확인해보면 됩니다.

이 중에서 한번 ctpvNm을 가져오려면 어떻게 하면 될까요?

먼저 가장 큰 부분인 response부터 시작해서 response -> body -> Items -> Item -> ctpvNm 의 순서로 structure를 구성하여 정보를 빼내면 되겠다는 것을 확인해줍니다.

가장 먼저 response를 담는 structure인 Response를 만들어줍니다. 그리고 그 안의 요소인 response는 Body 타입으로 지정해주었습니다. (Body type은 임의로 붙인 이름으로 다른 이름을 사용해도 무관합니다. 다만 우리가 타고 들어갈 response ->body -> Items -> Item -> ctpvNm는 임의로 이름을 지어서는 안되고 반드시 JSON에 나온 명칭을 그대로 사용해주어야 합니다. )

1
2
3
struct Response: Codable {
    let response: Body
}
cs

이번에는 Body structure를 선언합니다.

1
2
3
struct Body: Codable {
    let body: Items
}
cs

다음으로는 Items structure를 선언합니다.

1
2
3
struct Items: Codable {
    let items: Item
}
cs

그 다음으로는 Item structure를 선언해주면 되겠죠?

item의 경우는 array 구조이기 때문에 데이터 타입도 array 형태로 설정해주어야만 합니다.

1
2
3
struct Item: Codable {
    let item: [CityInfo]
}
cs

마지막으로 CityInfo structure를 선언해주면 끝입니다!

1
2
3
struct CityInfo: Codable {
    let ctpvNm: String
}
cs

더 이상 타고 들어갈 자료가 없고 ctpvNm은 String형태이므로 String으로 타입을 명시해주면 됩니다.

설정해야 하는 것이 많지만 그래도 하는 방법만 알면 전혀 어렵지 않습니다.

 

그런 다음 parsing을 해줍니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
guard let data = data else {
            return
        }
        
        do {
            let decodedData = try JSONDecoder().decode(Response.self, from: data)
            
            print(decodedData.response.body.items.item[0].ctpvNm)
            //"인천"
            
        } catch let jsonErr {
        print("Error serializing:", jsonErr)
    }
cs

이번 JSON은 array안에 담겨 있지 않았기 때문에 decode하는 데이터 형태에 [Response]가 아닌 Response를 그대로 입력해주면 됩니다. 

 

강의에서 알려준 JSON 형태와 다른 JSON을 맞닥트렸을 때 상당히 머리가 복잡했는데, 

구글링 및 시행착오로 그 방법을 알고나니 JSON parsing이 오히려 재밌어졌습니다. 데이터를 유용하게 사용하는 것에도 관심이 많은 저는 API를 잘 활용하여 작은 프로젝트도 해볼까 생각 중입니다. 

 

혹시 질문이 있으시거나 잘못된 부분, 개선점 등 알려주실 분들은 편하게 댓글 남겨주세요! 

감사합니다 ☺️ 

반응형