[Sesac IOS] 40일차 TIL
TIL

[Sesac IOS] 40일차 TIL

40일차 수업 내용을 정리한 글입니다.


Learned

Codable

1. 개요

A type that can convert itself into and out of an external representation.
Codable is a type alias for the  Encodable and Decodable protocols.
  • Encodable과 Decodable 프로토콜을 모두 포함하는 typealias
    (Encodable과 Decodable 중 하나만 지원한다면 사용 불가)
  • 클래스, 구조체같은 내부 객체가 JSON같은 외부적 표현으로 변환(convert)될 수 있도록
    인코딩 및 디코딩이 가능하게 해주는 기능을 함.
  • JSON 형식 뿐만 아니라, 데이터를 디스크에 저장하거나 네트워크로 전송할 때
    필요한 다른 형식으로 변환하게 해주는 역할

2. JSONSerialization VS Codable

  • JSONSerialization은 JSON 객체(사전)와 Data 객체 사이의 변환만 가능하지만
    Codable은 커스텀 타입과 상호 변환이 가능함.
  • JSON 형식에서 단일 값만 가져오는 경우 JSONSerialization이 빠르지만
    중첩된 구조 또는 반복적으로 데이터를 가져올 때 등 복잡한 상황에서는 Codable이 더 빠르다.
  • SwiftyJSON은 JSONSerialization을 활용한 라이브러리로 상대적으로 속도가 느리지만
    사전 형태로 데이터에 접근할 수 있음.

성능 비교

3. Decodable

  • 외부 형식을 내부 데이터 모델(클래스, 구조체, 열거형)로 디코딩할 수 있게 해주는 프로토콜
  • 구조체, 열거형, 클래스에서 채택할 수 있으며 Decodable을 채택하는 타입은
    외부 형식으로부터 디코딩이 가능한 타입이라는 것을 의미함.
  • 기본적으로 변환하려는 데이터의 키와 타입이 일치해야 하지만,
    별도의 처리를 통해 다른 키 이름을 쓰거나 다른 타입으로 변환할 수 있음.
  • 내부 형식으로 변환되지 못한 데이터는 nil값을 가짐. (단, 데이터 타입이 옵셔널일 때)
만약 변환하려고 하는 내부 형식의 키와 데이터 타입이 외부 형식과 일치하지 않으면 디코딩에 실패함.
외부 형식의 데이터 일부만 디코딩하는 것은 문제가 없음.
  • Key Decoding
    • JSONDecoder.KeyDecodingStrategy.convertFromSnakeCase
      → snake-case로 된 key를 camel-case key로 변환함.
    • CodingKey
      • 인코딩 및 디코딩 시 키로 사용할 수 있는 타입을 의미하며, 
        외부 형식과 다른 키 이름을 사용할 수 있게 커스텀 키를 설정할 수 있음.
      • 타입 안에 CodingKey 프로토콜을 채택하는 열거형을 만들어서 사용
    • Decodable.init(from decoder: Decoder)
      • 외부 형식의 데이터 값을 변형해서 내부 형식으로 저장하고 싶을 때 사용함.
      • 디코딩을 하면서 원하는 결과를 바로 얻고 싶을 때 용이함.
struct Game: Decodable {
    
    let title: String
    let playTime: Int?
    let publisher: String
    let isOnwed: Bool
    
    // 인코딩, 디코딩 시 사용될 키를 명시해줌
    enum CodingKeys: String, CodingKey {
        case title = "gameName"
        case publisher = "company"

	// 커스텀 키를 사용하지 않더라도 모든 key를 case로 만들어주어야 함.
        case playTime
    }
    
    init(from decoder: Decoder) thorws {
    	let container = try decoder.container(keyedBy: CodingKeys.self)
        title = try container.decode(String.self, forKey: .title)
        // 키에 해당하는 값이 null일 때 nil 반환
        playTime = (try? container.decodeIfPresent(Int.self, forKey: .playTime)) ?? 0
        publisher = try container.decode(String.self, forKey: .publisher)
        
        // 외부 형식과 매칭되는 키 없이 자체적으로 값을 초기화
        isOnwed = playTime > 0 ? true : false
    
    
    }
    
}

4. Encodable

  • 내부 형식으로된 데이터 모델을 JSON같은 외부 형식으로 인코딩할 수 있게 해주는 프로토콜
  • 인코딩 팁
    • outputFormatting: 인코딩된 json 객체의 가독성, 사이즈, 정렬 방식을 설정하는 프로퍼티
      prettyFormatting, sortedKeys 등이 있음.
    • dateEncodingStrategy: Date 타입을 어떻게 변환할 것인지 결정하는 프로퍼티
      formatter(DateFormatter 객체를 사용), iso8601(날짜 데이터 교환에 대한 국제 표준) 등이 있음.
    • Encodable.encode(to encoder: Encoder)
      • 인자 encoder를 사용해 값의 인코딩을 실행하는 메서드
      • Encoder 객체의 container를 사용해서 각 키에 대해 인코딩할
        구체적인 값을 지정해줄 수 있음.
struct User: Encodable {
    
    let name: String
    let age: Int
    let signDate: Date
    
    enum CodingKeys: CodingKey {
        case name
        case age
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode("\(age)살", forKey: .age)
        try container.encode(name, forKey: .name)
    }

}

 

JSON 형식의 데이터를 커스텀 타입 모델로 만들어주는 사이트: https://app.quicktype.io/

이상입니다.

'TIL' 카테고리의 다른 글

[Sesac IOS] 42일차 TIL  (0) 2022.08.31
[Sesac IOS] 41일차 TIL  (2) 2022.08.31
[Sesac IOS] 39일차 TIL  (0) 2022.08.29
[Sesac IOS] 38일차 TIL  (0) 2022.08.25
[Sesac IOS] 37일차 TIL  (0) 2022.08.25