원문(블로그 이전)
시리즈 | 🚀 iOS 네트워킹 정복하기 - averycode.log
요즘은 블로그대신 github 에 학습내용을 정리를 하게 되었는데,오랜만에 velog로 돌아와 iOS 네트워킹을 정복 시리즈를 작성해봅니다.iOS를 공부한지 몇개월이 지났는데 바쁘다는 핑계(?)로 네트워
velog.io
이번 시간에는 key 이름을 커스텀할때 사용할 수 있는 Coding Key 와 직접 인코딩과 디코딩을 구현하는 방법에 대해 알아보겠습니다.
그전에 왜? 커스텀 할일이 생길까요?
api 응답 데이터가 Camel Case 가 아니라 snake case 라던가 다른 형식을 사용하는 경우 swift 의 컨벤션에 맞지 않는데 요러한 경우에 사용할 수 있습니다.
다시한번 자세히 설명하면!
일반적으로 데이터 통신을 위한 모델을 만들때, Codable Protocol 을 채택하는데요
이때, 구현하려는 구조체 속성과 JSON Data 의 key값이 일치해야 정상적으로 Decoding 할 수 있습니다
근데 그게 쉽지 않죠..? 그때 CodingKeys 를 사용해주면 됩니다.
Coding Keys
애플 공식문서에서는 인코딩/디코딩을 위한 키로 사용할 수 있는 타입이라고 정의가 되어있습니다.
그럼 사용법을 알아봅시다.
openweathermap api의 결과 일부입니다! 딱봐도 Swift 에서 사용하기 그렇죠?
이러한 구조체를 데이터를 받고자합니다.
struct Temp: Codable {
let temp: Double
let feelsLike: Double
let minTemp: Double
let maxTemp: Double
}
그럼 아래의 단계를 거치면 됩니다.
- mapping 될 속성을 CodingKeys 열거형에 추가한다
- CodingKeys 열거형은 CodingKey 프로토콜을 채택한다.
- mapping 이 달라지는 속성의 rawValue 로 필요한 JSON Data의 키 값을 입력합니다.
struct Temp: Codable {
let temp: Double
let feelsLike: Double
let minTemp: Double
let maxTemp: Double
enum CodingKeys: String, CodingKey {
case temp
case feelsLike = "feels_like"
case minTemp = "temp_min"
case maxTemp = "temp_max"
}
}
Encode and Decode Manually
이누님의 블로그를 참고했습니다
다음과 같은 경우 인코딩 및 디코딩 과정을 직접 구현하여 자신만의 인코딩 및 디코딩 로직을 작성할 수 있습니다.
- 인코딩 혹은 디코딩 시점에 값을 검증하거나 제약을 주고 싶은 경우
- 기본으로 제공되는 인코딩 및 디코딩 객체에 제공되는 속성이나 CodingKeys로는 원하는 결과를 만들 수 없는 경우
Encoding
struct Member: Codable {
var name: String
var age: Int
var job: String?
func encode(to encoder: Encoder) throws {
var container = encoder.contatiner(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
guard (20...30).contains(age) else { throw EncodingError.invalidRange }
try container.encode(age, forKey: .age)
try container.encodeIfPresent(job, forKey: .job)
}
}
- encoding 처리된 데이터는 encoder 내부에 container 형태로 저장되기 때문에 해당 컨테이너를 먼저 가져온다.
- containter : CodingKey 열거형에 존재하는 Key 값과 속성을 매핑할 수 있다.
- container.encode를 통해 내부 속성을 Key값과 매핑시켜 저장
- guard 문을 통해 범위를 확인하고 범위에 해당하지 않는 경우 에러를 방출
- 이때, EncodingError.invalidRange는 직접 선언한 Error이다.
- optional 값의 경우 encodeIfPresent 을 사용
Decoding
struct Member: Codable {
var name: String
var age: Int
var job: String?
init(from decoder: Decoder) throws {
let container = decoder.contatiner(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
age = try container.decode(Int.self, forKey: .age)
guard (20...30).contains(age) else { throw EncodingError.invalidRange }
job = try container.decodeIfPresent(String.self, forKey: .job)
}
}
- encoder 와 마찬가지로 container 를 가져옵니다.
- container.decode를 통해 원하는 key의 값을 원하는 타입으로 받아옵니다.
- guard 문을 통해 범위를 확인하고 범위에 해당하지 않는 경우 에러를 방출
- 이때, EncodingError.invalidRange는 직접 선언한 Error이다.
- optional 값의 경우 decodeIfPresent 을 사용
Container Type
인코딩과 디코딩을 customizing 할때 사용하는 컨테이너 타입에 대한 자세한 내용은
KeyedEncodingContainerProtocol 및 UnkeyedEncoding Container 를 참고
References
https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types
https://inuplace.tistory.com/1224?category=1058164
https://tech.burt.pe.kr/swift/codable/encoding-decoding-custom-type
'이전 블로그 > iOS Dev' 카테고리의 다른 글
🚀 iOS 네트워킹 정복하기 (5) ATS (App Transport Security) (0) | 2022.11.02 |
---|---|
🚀 iOS 네트워킹 정복하기 (3) Codable Protocol ( JSON Encoding / Decoding) (1) | 2022.11.02 |
🚀 iOS 네트워킹 정복하기 (2) URLSession (1) | 2022.11.02 |
🚀 iOS 네트워킹 정복하기 (1) Kick Off (0) | 2022.11.02 |
[Swift] Struct와 Class (feat. 값타입과 참조타입) (0) | 2022.11.02 |