일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- RealmSwift
- programmers
- Pod
- swift
- SwiftGen
- pbxgroup
- UITableView
- pbxfilesystemsynchronizedrootgroup
- CustomCode
- issecuretextentry
- 프로그래머스
- Xcode
- JSONSerialization
- 위클리챌린지
- Custom PageViewController
- cocoapods
- 정보처리기사 실기
- JSON
- 정보처리기사
- storybaord
- JSONParser
- IOS
- 정보처리기사 실기 요약본
- 2018 KAKAO BLIND RECRUITMENT
- parse
- 티스토리챌린지
- PageViewController
- dynamic height
- Decodable
- Codable
- Today
- Total
iOS 개발일기
[Swift] JSONParser - JSONSerialization 본문
오늘은 JSON 파싱 방법 중 하나인 JSONSerialization에 대해서 알아보겠습니다.
JSONSerialization은 Decodable에 비해 제약이 심하지 않죠.
그렇지만 Decodable이 워낙 간단하게 구현할 수 있는지라...
기본적인 JSONSerialization
먼저 문자열을 하나 선언해주겠습니다.
let jsonString = """
{
"user_id" : 0,
"user_name" : "hoon",
"user_age" : 30
}
"""
그 다음 JSONSerialization을 해보도록 하겠습니다.
guard let data = jsonString.data(using: .utf8) else {return}
do {
guard let dic = try JSONSerialization.jsonObject(with: data) as? [String:Any] else {return}
if let userId = dic["user_id"] as? Int {
print(userId)
}
if let username = dic["user_name"] as? String {
print(username)
}
if let age = dic["user_age"] as? Int {
print(age)
}
} catch {
print("parse error:", error)
}
현재에는 데이터에 하나의 Dictionary만 존재하기 때문에 [String:Any] 타입으로 캐스팅해주는 것입니다.
(그리고 바인딩은 캐바캐지만 저같은 경우에는 되도록 바인딩을 통해서 예외처리를 해주는 편입니다.)
만약, 받아야 하는 데이터가 배열일 경우에는 배열로 캐스팅해주셔야합니다.
guard let arr = try JSONSerialization.jsonObject(with data) as? [[String:Any]] else {return}
이렇게 Array<Dictionary<String:Any>>로 해주셔야 됩니다.
(이 외에도 다른 형태들이 다양하게 존재하기 때문에 데이터의 형태를 잘 파악하신 다음에 캐스팅해주셔야 데이터를 받을 수 있습니다.)
자 기본적인 사용법을 봤으니 이제 데이터를 모델로 사용해보는 방법을 알아보겠습니다.
데이터를 담을 모델을 생성해보겠습니다.
Struct User {
private(set) uid: Int
private(set) name: String
private(set) age: Int
init(from dic: [String:Any]) {
self.uid = (dic["user_id"] as? Int) ?? 999
self.name = (dic["user_name"] as? String) ?? ""
self.age = (dic["user_age"] as? Int) ?? 0
}
}
필요한 데이터는 모두 적어주시고 Dictionary를 받아 초기화해줄 예정입니다.
JSONSerialization 사용은 기본적인 방법과 별로 다르지않습니다.
guard let data = jsonString.data(using: .utf8) else {return}
do {
guard let dic = JSONSerialization.jsonObject(with: data) as? [String:Any] else {return}
let user = User(from: dic)
print(user.uid) //0
print(user.name) //hoon
print(user.age) //30
} catch {
print("parse error:", error)
}
이렇게 간단하게 Instance를 사용할 수 있습니다.
지금까지는 기본적인 JSONSerialization을 사용하는 법을 알아보았습니다.
Decodable이 나온 현재에는 JSONSerialization은 잘 안쓰는 편이긴 합니다만
받아오는 Data의 값들 중에서 필요한 값이 하나일 경우에는 Decodable Instance를 생성하는 것은 필요한 Data에 비해 너무 과한 비용을 투자하는 것 같아서 JSONSerialization을 사용합니다.
예를 들어 보겠습니다.
let jsonString = """
{
"result" : true,
"a" : "",
"b" : 1
}
"""
좀 극단적인 예이기는 합니다만..ㅎㅎ
이런 JSON에서 나에게 'result'라는 데이터만 필요할 경우에는 Decodable Instance를 생성하기에는 배보다 배꼽이 큰 경우인 것 같아
JSONSerialization을 통해서 하나의 값만 가져오게 설계를 하는 것 같아요.
guard let data = jsonString.data(using: .utf8) else {return}
do {
guard let dic = try JSONSerialization.jsonObject(with: data) as? [String:Any] else {return}
if let result = dic["result"] as? Bool {
print(result) //true
}
} catch {
print("parse error:", error)
}
이렇게 말이죠
함수를 만들어서 범용적으로 사용할 수 있게 만들어준다면 데이터 안에 하나의 파라미터만 필요로 할 때에는
Decodable을 사용하는 것 보다 JSONSerialization이 조금 더 낫지않나 이런 생각을 하면서 사용하고 있습니다...
(제 의견과 다른 분이 있으시다면 댓글에 이유를 알려주세요!)
func parse<T>(_ type: T.Type, from jsonString: String) -> T? {
guard let data = jsonString.data(using: .utf8) else {return nil}
do {
return try JSONSerialization.jsonObject(with: data) as? T
} catch {
print("parse error:", error)
}
return nil
}
'iOS > Swift' 카테고리의 다른 글
[Swift] 'didSelectItemAt' 함수가 호출되지 않는 이유 (2) | 2023.12.07 |
---|---|
[Swift] Custom PageViewController (0) | 2022.03.22 |
[Swift] JSONParser - Decodable(2) (0) | 2022.03.15 |
[Swift] JSONParser - Decodable(1) (0) | 2022.03.14 |
[Swift] iOS 15, UINavigationBar barTintColor 적용 방법 (0) | 2021.09.28 |