Codable이란?
외부 표현과의 호환성을 위해 데이터 유형을 인코딩/디코딩할 수 있는 프로토콜.
JSON 데이터 등을 인코딩/디코딩하기 위해 사용됨
Decodable
데이터를 원하는 모델의 형식으로 디코딩할 수 있도록 만든 프로토콜
// json data
let json = """
{
"quote": "Count your age by friends, not years. Count your life by smiles, not tears.",
"author": "John Lennon"
}
"""
// MARK: Quote
struct Quote: Decodable {
let quote: String
let author: String
}
// MARK: String -> Data 형식으로 바꿔주기 -> Quote에 담아주기
// 1. String -> Data
guard let result = json.data(using: .utf8) else { fatalError("ERROR")}
print(result)
// 2. Data -> Quote
do {
let value = try JSONDecoder().decode(Quote.self, from: result)
print(value)
} catch {
print(error)
}
예제) JSON 데이터를 가져왔고 Quote라는 구조체를 만들었다.
JSON 데이터를 Quote의 형식으로 저장하기 위해서는 String인 JSON을 Data 형식으로 바꿔준 뒤, 구조체에 담아주어야 한다.
1. String -> Data 로 변환하기 위한 코드와
2. Data -> Quote 로 변환하기 위한 코드를 작성하였다.
DecodingStrategy
주의해야 할 점은
키가 완벽하게 일치하지 않으면 실행이 아예 안 될 수도 있다는 것.
- 1. 가장 쉽게 고치는 방법은?
- 옵셔널로 정의한다. String? ⇒ 그러나 모든 해결책은 아님
- 2. snake_case에서 camelCase로 변환?
- snake_case에서 변환하는 Strategy를 추가해주면 변경된다
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
- 3. 아예 키 이름을 다르게 정의하고 싶다면?
- CodingKey 프로토콜 사용
struct Quote: Decodable {
let quote: String
let author: String
enum CodingKeys: String, CodingKey { // 내부적으로 선언되어 있는 열거형
case quote = "quote_content"
case author = "author_name"
}
}
- 서버에서 값을 3개 줬는데 4개로 만들고 싶을 경우?
- init으로 선언해준다
let json = """
{
"quote_content": "Count your age by friends, not years. Count your life by smiles, not tears.",
"author_name": null,
"like_count": 12345
}
"""
struct Quote: Decodable {
let quote: String
let author: String
let like: Int
let isInfluencer: Bool // 10000개 이상 좋아요 받은 경우
enum CodingKeys: String, CodingKey { // 내부적으로 선언되어 있는 열거형
case quote = "quote_content"
case author = "author_name"
case like = "like_count"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
quote = try container.decode(String.self, forKey: .quote)
author = try container.decodeIfPresent(String.self, forKey: .author) ?? "unknown" // null이라면 unknown으로
like = try container.decode(Int.self, forKey: .like)
isInfluencer = (10000...).contains(like) ? true : false
}
}
Encodable
모델 데이터를 외부로 전달하기 위해 JSON 데이터 등으로 변환할 때 사용하는 프로토콜
// User
struct User: Encodable {
let name: String
let signDate: Date
let age: Int
}
// users
let users: [User] = [
User(name: "Ziuge", signDate: Date(), age: 33),
User(name: "Elsa", signDate: Date(timeInterval: -86400, since: Date()), age: 18),
User(name: "Emily", signDate: Date(timeIntervalSinceNow: 86400*2), age: 11)
]
do {
// 1. User -> Data
let result = try JSONEncoder().encode(users)
print(result)
// 2. Data -> String
guard let jsonString = String(data: result, encoding: .utf8) else {
fatalError("ERROR")
}
print(jsonString)
} catch {
print(error)
}
모델 -> Data -> String 의 순서로 변경한다
(Decodable과 반대)
EncodableStrategy
- prettyPrinted : JSON 데이터를 깔끔하게 보고 싶을 때
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
- dateEncodingStrategy : 날짜를 깔끔하게 보여줌
encoder.dateEncodingStrategy = .iso8601
'공부하자! > iOS' 카테고리의 다른 글
메모마무 개발 - 중간 발표 이후 (0) | 2022.09.26 |
---|---|
[TIL] GCD - Main/Global, sync/async 실습 (22.09.02) (3) | 2022.09.06 |
[TIL] CodeBase UI + 코드 예제 (0) | 2022.08.18 |
[TIL] 타입캐스팅 (0) | 2022.08.18 |
[TIL] 모듈화, 프레임워크, 접근 제어 (0) | 2022.08.17 |