Codable
API는 개발자가 JSON 같은 데이터를 쉽게 encode 및 decode 할 수 있게 해준다.- 사실,
Codable
은 Encodable
과 Decodable
Protocol의 type alias이다.
자동화
Encodable
이든 Decodable
을 채택하면 자동으로 필요한 stored property를 encode 혹은 decode 한다.
struct User: Codable {
var name: String
var age: Int
}
Encode
- 다음과 같이
JSONEncoder
를 통해 JSON 데이터로 쉽게 encode 할 수 있게 된다.
do {
let user = User(name: "Hohyeon", age: 22)
let encoder = JSONEncoder()
let data = try encoder.encode(user)
} catch {
print("Whoops, I did it again: \(error)")
}
Decode
- 다음과 같이
JSONDecoder
를 통해 JSON 데이터를 쉽게 decode 할 수도 있다. - 다음 코드를 실행하면 정확히 우리가 넣었던 JSON 데이터가 나올 것이다.
let decoder = JSONDecoder()
let secondUser = try decoder.decode(User.self, from: data)
문제점
- JSON 데이터 형식이 개발자가 원하는 형식이면 상관 없지만 그렇지 않으면 문제가 있다.
- 다음과 같은 JSON 코드를 decode 하려고 했다고 생각해보자.
- 위의 코드를 사용해 자동으로 encode 및 decode 할 수 없을 것이다.
{
"user_data": {
"full_name": "Hohyeon Moon",
"user_age": 22
}
}
해결법
- 여러 해결 방법이 있지만, 그 중에서 제일 간단하고 효율적인 방법에 대해 알아보겠다.
- User 구조체를 확장해, Codable을 채택한 CodingData 구조체를 만든다.
- 그리고 그 안에 다시 Codable을 채택한 Container 구조체를 만든다.
- Container 안에 JSON 데이터의 camelCase 변수명을 만든다.
extension User {
struct CodingData: Codable {
struct Container: Codable {
var fullName: String
var userAge: Int
}
var userData: Container
}
}
- 그리고 다음과 같이 User.CodingData 타입을 확장해 User 인스턴스에 값을 넣어준다.
extension User.CodingData {
var user: User {
return User(
name: userData.fullName,
age: userData.userAge
)
}
}
- snake_case를 camelCase로 변경하기 위해 convertFromSnakeCase를 사용한다.
- 직접 decode 하는 대신, User.CodingData의 인스턴스를 decode 하고 그것을 user로 convert 한다.
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let codingData = try decoder.decode(User.CodingData.self, from: data)
let user = codingData.user