안녕하세요~ 차니에요!
오늘은 Codable에 대해 알아보도록 하겠습니다.
개념부터 예제까지 순서대로 나열되어 있으니 천천히 따라와 주세요 :D
1. Codable 이란?
이 내용만 봐서는 Codable이 뭔지 감이 잘 안오시죠?
Codable 안의 Decodable과 Encodable을 보고 다시 보도록하겠습니다.
2. Decodable & Encodable
1번의 Declartion을 보면 Codable은 Decodable & Encodable 으로 두 프로토콜을 모두 준수하는 프로토콜입니다.
한마디로 Codable 프로토콜을 채택했다는 것은 JSON 디코딩과 인코딩 모두 가능하다는 뜻으로 볼 수 있습니다.
아래 예제를 통해 더 자세히 알아보도록 하겠습니다.
3. Codable 예제
Codable을 채택한 class, struct, enum 등을 선언해줍니다.
struct Coffee: Codable {
let name: String?
let price: Int?
let stock: Int?
}
저는 Coffee struct를 생성했고 name, price, stock을 멤버 변수로 담아주었습니다.
여기서 눈여겨볼 부분은 변수에 타입 어노테이션을 통해 Optional 변수로 지정해 주었다는 점입니다.
서버에서 데이터를 내려주고 파싱 할 때 해당 값이 없거나 null이라면 파싱 에러가 나기 때문입니다.
3-1. Encodable
먼저 struct 타입을 JSON 형태로 인코딩하는 방법입니다.
let menu = Coffee.init(name: "아메리카노", price: 2000, stock: 100)
if let data = try? JSONEncoder().encode(menu) {
print("data = \(String(decoding: data, as: UTF8.self))")
}
인자가 제네릭으로 선언되어있고 Encodable을 채택해야한다는 조건, 예외가 발생할 수 있다는 throws 처리가 되어있습니다.
예제 코드를 보면 encode 인자로 struct 타입을 넘겨주었습니다. (제네릭)
Coffe struct는 Codable을 채택하고 있으므로 Encodable과 Decodable을 동시에 채택하고 있습니다.
마지막으로 예외가 발생할 수 있는 메서드이기 때문에 try? 로 처리해준 모습입니다.
3-2. Decodable
이번에는 JSON 형식의 데이터를 struct 타입으로 변환하는 예제입니다.
data는 서버에서 내려주는 데이터라고 가정하겠습니다.
let data = """
{
"name":"아메리카노",
"price":2000,
"stock":100
}
""".data(using: .utf8)
if let data = try? JSONDecoder().decode(Coffee.self, from: data!) {
print("data = \(data)")
print("name = \(data?.name)")
print("price = \(data?.price)")
print("stock = \(data?.stock)")
}
3-1 과 같은 맥락이니 이해되셨을겁니다!
4. CodingKey
엄청 간편하게 통신 데이터를 인코딩/디코딩 할수 있었죠?
지금까지는 struct의 변수명과 서버에서 내려주는 키값이 동일했었는데요.
만약 두 값이 달라지면 파싱이 정상적으로 이루어지지 않아서 nil을 반환할겁니다.
이를 해결 하기위해 CodingKey라는 녀석을 사용해볼건데요.
개념부터 보고 가겠습니다.
쉽게 말해 struct의 변수명과 서버에서 내려주는 키 값이 달라도 정상적으로 파싱할 수 있게 해주는 프로토콜입니다.
아래 예제를 통해 더 알아보도록 하겠습니다.
struct Coffee: Codable {
let name: String?
let price: Int?
let stock: Int?
enum CodingKeys: String, CodingKey {
case name = "ServerName"
case price, stock
}
}
이렇게 정의하면 서버에서 "ServerName"이라는 키 값으로 값을 내려준다면 name으로 파싱됩니다.
let data = """
{
"ServerName":"아메리카노",
"price":2000,
"stock":100
}
""".data(using: .utf8)
if let data = try? JSONDecoder().decode(Coffee.self, from: data!) {
print("data = \(data)")
print("name = \(data.name)")
print("price = \(data.price)")
print("stock = \(data.stock)")
}