관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swfit] Codable 사용방법 (Encode, Decode) 본문

iOS 응용 (swift)

[iOS - swfit] Codable 사용방법 (Encode, Decode)

jake-kim 2020. 10. 18. 16:48

Codable이란? Encodable + Decodable 두 속성 모두 가지고 있는 타입

  • Encodable: 스위프트의 struct구조의 "객체"를 "json형식"으로 변한 하는 것 (Binary Data로 변환)
  • Decodable: "json형식"을 "객체"로 변환

필요한 이유: 서버와 통신할 경우, 객체 그대로를 보내지 / 받지 않고, Binary Data로 통신

Encode

  • swift의 struct객체 -> Binary Data (json형)
  • struct정의
struct Person: Codable {
    var name: String
    var age: Int
    var birthDate: Date
}

Encode_ Binary데이터 변환

// create
let person = Person(name: "jake", age: 27, birthDate: Date(timeIntervalSince1970: 0))
print(person) // Person(name: "jake", age: 27, birthDate: 1970-01-01 00:00:00 +0000)

// encode
let encoder = JSONEncoder()
do {
    let jsonData = try encoder.encode(person)
    print(jsonData) // 47 bytes
} catch {
    print(error)
}

Encode_ json포멧으로 변환

  • encoder.outputFormatting = .prettyPrinted
// json format (normal)
encoder.outputFormatting = .prettyPrinted
do {
    let jsonData = try encoder.encode(person)
    if let jsonStr = String(data: jsonData, encoding: .utf8) {
        print(jsonStr)
        /*
         {
           "name" : "jake",
           "age" : 27,
           "birthDate" : -978307200
         }
         */
    }
} catch {
    print(error)
}

Encode_ snake_case로 변환

  • encoder.keyEncodingStrategy = .convertToSnakeCase
// json format (snake_case)
encoder.keyEncodingStrategy = .convertToSnakeCase
do {
    let jsonData = try encoder.encode(person)
    if let jsonStr = String(data: jsonData, encoding: .utf8) {
        print(jsonStr)
        /*
         {
           "name" : "jake",
           "age" : 27,
           "birth_date" : -978307200
         }
         */
    }
} catch {
    print(error)
}

Encode_ Date 포멧 (ISO8601)

  • encoder.dateEncodingStrategy = .iso8601
// date format (ISO 8601)
encoder.dateEncodingStrategy = .iso8601
do {
    let jsonData = try encoder.encode(person)
    if let jsonData = String(data: jsonData, encoding: .utf8) {
        print(jsonData) // "birth_date" : "1970-01-01T00:00:00Z"
    }
} catch {
    print(error)
}

 

Decode

  • Binary data -> swift의 객체
  • key값이 struct와 다르다면, Codingkeys로 정의
struct Tree: Codable {
    var name: String
    var height: String
    var treeCategory: String

    enum CodingKeys: String, CodingKey {
        case name
        case height
        case treeCategory = "tree_category"
    }
}

Decode_ 변환

let jsonData =
"""
{
    "name": "jake",
    "height": "29",
    "tree_category": "sonamu"
}
""".data(using: .utf8)!

let decoder = JSONDecoder()
do {
    let result = try decoder.decode(Tree.self, from: jsonData)
    print(result) // Tree(name: "jake", height: "29", treeCategory: "sonamu")
} catch {
    print(error)
}

Decode_ 서버에서 특정 필드에 값을 내려주지 않는 경우 대비

  • Codable타입의 struct의 초기화 구문에서 "??" 연산자 사용
  • struct에 optional로 하려면 옵셔널 바인딩을 해야하는 번거로움이 생기므로 init구문 사용
// 원래 아래와 같이 default로 init이 존재
init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    name = try values.decode(String.self, forKey: .name)
    isOpen = try values.decode(String.self, forKey: .isOpen)
}
  • 아래와 같이 정의하여 Optional 대비
init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    name = (try? values.decode(String.self, forKey: .name)) ?? "empty"
    isOpen = (try? values.decode(String.self, forKey: .isOpen)) ?? "no"
}

 

* codable을 이용하여 json파싱하는 여러가지 예제: ios-development.tistory.com/161

Comments