⭐️Codable, JSON⭐️
Codable 프로토콜을 통해 JSON 데이터를 인코딩, 디코딩 해보자.
https://toughie-ios.tistory.com/113
JSON Parsing
JSON이란? JavaScriptObjectNotation의 약자. JSON의 문법이 자바스크립트 문법과 유사하지만 자바스크립트에서만 사용되는 것이 아니라 JSON Parsing을 지원하는 프로그래밍 언어에서는 다 사용할 수 있다.
toughie-ios.tistory.com
예전에 작성한 게시글을 한 번 훑고 시작하기.
- JSON은 데이터 교환을 위한 가벼운 데이터 형식
- Encoding은 특정 데이터를 JSON으로 변환
- Decoding은 JSON 데이터를 필요한 데이터 형태로 변환(보통 JSON Parsing, 파싱이라고 함)
데이터 모델
struct CustomerModel: Identifiable { //Encodable, Decodable, Codable
// let id = UUID().uuidString
//보통 위와 같이 랜덤 아이디를 부여하기도 하지만, 여기서는 id를 JSON으로 받아온다고 가정
let id: String
let name: String
let points: Int
let isVIP: Bool
}
뷰 모델
final class CodableViewModel: ObservableObject {
@Published var customer: CustomerModel?
init() {
getData()
}
...
func getData() {
...
}
func getJSONData() {
...
}
}
JSON ENCODING
func getJSONData() -> Data? {
// ENCODING용 더미 딕셔너리
let dictionary: [String: Any] = [
"id": "77777",
"name": "Toughie",
"points": 7,
"isVIP": true
]
let jsonData = try? JSONSerialization.data(withJSONObject: dictionary, options: [])
return jsonData
}
만약 CustomerModel이 Encodable 프로토콜을 채택했다면?
// let customer = CustomerModel(id: "12345", name: "TAF", points: 9, isVIP: false)
// let jsonData = try? JSONEncoder().encode(customer)
}
JSONSerialization 클래스의 data(withJSONObject:options:)메서드를 통해
dictionary를 JSON 데이터로 변환.
주어진 Dictionary를 JSOn 형식으로 *직렬화하고 이를 Data 객체로 반환.
*직렬화
객체나 데이터 구조를 일련의 바이트(byte)로 변환하는 과정.
주로 데이터를 저장하거나 전송하기 위해 사용됨.
-> 원래 형태로 복원 용이(역직렬화), 바이트로 표현되기 때문에 파일이나 네트워크 등에서 전송 및 저장 용이
JSON DECODING
manual decoding
func getData() {
//JSON 데이터를 받아와서
guard let data = getJSONData() else { return }
if
//options -> 역직렬화 작업 세부 제어용
let localData = try? JSONSerialization.jsonObject(with: data, options: []),
//Any 타입을 [String: Any]로 타입캐스팅
let dictionary = localData as? [String: Any],
//각 키에 해당하는 벨류를 타입별로 캐스팅
let id = dictionary["id"] as? String,
let name = dictionary["name"] as? String,
let points = dictionary["points"] as? Int,
let isVIP = dictionary["isVIP"] as? Bool {
//JSON 파싱을 통한 데이터를 가지고 새로운 인스턴스 생성
let newCustomer = CustomerModel(id: id, name: name, points: points, isVIP: isVIP)
customer = newCustomer
}
}
더 간편한 디코딩 방식
⭐️ 모델이 Decodable 프로토콜을 채택했을 경우
func getData() {
guard let data = getJSONData() else { return }
do {
//JSON 데이터를 CustomModel 타입으로 변환
self.customer = try JSONDecoder().decode(CustomerModel.self, from: data)
} catch let error {
print("ERROR DECODING: \(error.localizedDescription)")
}
//축약 ver
//self.customer = try? JSONDecoder().decode(CustomerModel.self, from: data)
}
EnCodalbe, Decodable, Codable
struct CustomerModel: Identifiable, Codable {
let id: String
let name: String
let points: Int
let isVIP: Bool
//MARK: ⭐️ CODABLE 채택하면 아래 전부 자동 구현됨 ⭐️
--------------------------------------------------------------------------------
//인코딩, 디코딩에서 키로 사용될 수 있는 코딩키
enum CodingKeys: String, CodingKey {
case id
case name
case points
case isVIP
}
//기본 생성자
init(id: String, name: String, points: Int, isVIP: Bool) {
self.id = id
self.name = name
self.points = points
self.isVIP = isVIP
}
//디코딩을 통해 초기화 하는 경우
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(String.self, forKey: .id)
self.name = try container.decode(String.self, forKey: .name)
self.points = try container.decode(Int.self, forKey: .points)
self.isVIP = try container.decode(Bool.self, forKey: .isVIP)
}
//JSON 데이터로 인코딩 하는 메서드
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(name, forKey: .name)
try container.encode(points, forKey: .points)
try container.encode(isVIP, forKey: .isVIP)
}
}
Encodable, Decodable 프로토콜의 동작 방식과, Codable 프로토콜의 강력함을 알 수 있는 부분.
내부적으로는 저런 과정을 거치는데 Codable 프로토콜만 채택해주면 번거로운 과정을 손쉽게 넘어갈 수 있다!
'SwiftUI > SwiftUI(Intermediate)' 카테고리의 다른 글
18. Combine 컴바인 .feat JSON (0) | 2023.06.13 |
---|---|
17. JSON Download with @escaping (0) | 2023.06.12 |
15. mask 마스킹 (0) | 2023.05.26 |
14. sheet 시트 사용법 / multiple sheets (0) | 2023.05.25 |
13. GeometryReader / rotation3DEffect (0) | 2023.05.25 |