본문 바로가기

iOS

[iOS] Codable and JSON Encoder & Decoder

Codable 그리고 JSON Encoder & Decoder

 

Codable


typealias Codable = Decodable & Encodable

인코딩 : 정보의 형태 또는 형식을 다른 형태, 형식으로 변환하는 처리 방식

 

디코딩 : 인코딩의 반대 작업

 

Codable은 스위프트의 인스턴스를 다른 데이터 형태로 변환하고 그 반대의 역할을 수행하는 방법을 제공해준다.

 

스위프트의 인스턴스를 다른 데이터 형태로 변환하는 것을 Encodable 프로토콜에 표현하였고, 그 반대로 다른 데이터 형태를 스위프트 인스턴스로 변환하는 것을 Decodable로 표현하였다.

Example

Coordinate 타입과 Landmark 타입의 인스턴스를 다른 데이터 형식으로 변환(인코딩)하고 싶은 경우, Codable 프로토콜을 준수하도록 하면 된다.

Codable 타입의 프로퍼티는 모두 Codable 프로토콜을 준수하는 타입이어ㅑ 한다.

struct Coordinate: Codable {
    var latitude: Double
    var longitude: Double

}

struct Landmark: Codable {
    var name: String
    var foundingYear: Int
    var vantagePoints: [Coordinate]
    var metadata: [String: String]
    var website: URL?
}

위 코드에 존재하는 두 개의 구조체 모두 Codable 프로토콜을 채택하고 있다.

 

이를 통해 해당 구조체의 인스턴스를 다른 데이터 타입 (ex: JSON)으로 변환하는 인코딩 작업 또는 타 테이터 타입을 위 구조체 인스턴스로 변환하는 디코딩 작업을 진행할 수 있다.

 

CodingKey

개발을 진행하다보면 JSON 형태의 데이터를 자주 다루게 되며 이를 상호 변환하고자 할 때는 기본적으로 인코딩/디코딩 할 JSON 타입(key:value)의 키와 애플리케이션의 사용자정의 프로퍼티가 일치해야 한다. -> 매우 중요한 포인트!!

 

만일 JSON의 키 이름을 구조체 프로퍼티의 이름과 다르게 표현하려면 CodingKey를 이용해야 한다.

Example

struct Landmark: Codable {
    var name: String
    var foundingYear: int
    var location: Coordinate
    var vantagePoints: [Coordinate]

    enum CodingKeys: String, CodingKey {
        case name = "title"  // Codable property = JSON Key
        case foundingYear = "founding_date" // Codable property = JSON Key

        // JSON 타입의 키와 구조체의 프로퍼티 이름이 동일하다면 값을 할당하지 않아도 무방하다.
        case location
        case vantagePoints
    }
}

위와 같이 CodingKeys 열거형을 작성한다.

 

프로퍼티의 열거형 케이스의 값으로 매칭할 JSON의 키 값을 작성하면 된다. ( case [프로퍼티명] = JSON key )

 

즉 실제 JSON 데이터의 키 값이 title인데 이를 Landmark.name에 매칭하고 싶은 경우에는 case name = "title" 과 같이 작성한다.

 

JSONEncoder / JSONDecoder

Codable 프로토콜을 채택해 작성한 모델을 JSONEncoder, JSONDecoder를 이용해 JSON 형식으로 인코딩 및 디코딩 할 수 있다.

 

즉, JSONEncoder 및 JSONDecoder를 활용하여 스위프트 타입의 인스턴스를 JSON 데이터로 인코딩, JSON 데이터에서 스위프트 타입의 인스턴스로 디코딩할 수 있습니다.

 

Codable 프로토콜을 준수하는 GroceryProduct 구조체의 인스턴스를 JSON 데이터로 인코딩 하는 방법이다.

struct GroceryProduct: Codable {
    var name: String
    var points: int
    var description: String?
}

let pear = GroceryProduct(name: "Pear", points: 250, description: "A ripe pear.")

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted

do {
    let data = try encoder.encode(pear)
    print(string(data: data, encoding: .utf8)!)
} catch {
    print(error)
}

/*
 {
   "name" : "Pear",
   "points" : 250,
   "description" : "A ripe pear."
 }
*/

1. JSONEncoder 인스턴스 생성 및 출력 옵션 지정 (ex: JSONEncoder.outputFormatting = .prettyPrinted)

2. JSON Encoding 진행. (try JSONEncoder.encode(DATA))

 

 

 

JSON 데이터를 Codable 프로토콜을 준수하는 GroceryProduct 구조체의 인스턴스로 디코딩 하는 방법이다.

struct GroceryProduct: Codable {
    var name: String
    var points: Int
    var description: String?
}

let json = """
{
    "name": "Durian",
    "points": 600,
    "description": "A fruit with a distinctive scent."
}
""".data(using: .utf8)!

let decoder = JSONDecoder()

do {
    let product = try decoder.decode(GroceryProduct.self, from: json)
    print(product.name)
} catch {
    print(error)
}

// "Durian"

 

1. JSONDecoder 인스턴스 생성 ( 디코딩 타입, 포맷 지정)

2. JSON Decoding 진행, (try JSONDecoder.decode(Type, Format))

 

 

'iOS' 카테고리의 다른 글

[iOS] Core Data  (0) 2020.07.11
[iOS] Storyboard vs Code-based UI & DispatchQueue  (0) 2020.07.05
[iOS] Searchable TableView  (0) 2020.06.30
[iOS] Sections, Headers, Footers in TableView  (0) 2020.06.27
[iOS] GCD (Grand Central Dispatch)  (1) 2020.06.24