관리 메뉴

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

[iOS - swift] json, codable, nestedContainer(keyedBy:forKey:), Encoding 중첩 모델 처리 방법 (인코딩) 본문

iOS 응용 (swift)

[iOS - swift] json, codable, nestedContainer(keyedBy:forKey:), Encoding 중첩 모델 처리 방법 (인코딩)

jake-kim 2022. 2. 8. 01:28

* 기본적인 Codable, Decode, Encode 개념은 이곳 참고

* 관련 포스팅 글

중첩 모델을 flatten 모델로 정의 방법

ex) 아래 json 데이터에서 blog_info.name.first 값만 encoding에 사용하고 싶은 경우, flat하게 모델 정의 방법?

{
  "user_id": "jake",
  "blog_info": {
    "name": {
      "first": "iOS 앱 개발 알아가기",
      "second": "SwiftUI 앱 개발 알아가기"
    }
  }
}
nestedContainer 사용 x - 중첩 nestedContainer 사용 o - flatten
  • 모델 정의
    • nested된 json key값들을 정의하기 위해 String, CodingKey를 준수하는 enum타입 여러개 정의
    • blog_info, name 두 개의 enum이 필요
struct MyModel {
  enum CodingKeys: String, CodingKey {
    case userID = "user_id"
    case blogInfo = "blog_info"
  }
  enum BlogInfoKeys: String, CodingKey {
    case name
  }
  enum NameKeys: String, CodingKey {
    case first
    case second
  }
  var userID: String?
  var blogName: String?
}
  • Encoding 정의
    • Encodable을 준수하고, encode(to encoder: Encoder) throws 메소드를 정의
      • cf) 디코딩인 경우, Decodable을 준수하고 init(from decoder: Decoder) throws 메소드 정의
    • nested에 접근할때는 nestedContainer를 통해 접근하고, encode시킬 프로퍼티가 생기면 encode(:forKey:)메소드 사용
      extension MyModel: Encodable {
        func encode(to encoder: Encoder) throws {
          var containerKeys = encoder.container(keyedBy: CodingKeys.self)
          try containerKeys.encode(self.userID, forKey: .userID)
          
          var blogInfoKeys = containerKeys.nestedContainer(keyedBy: BlogInfoKeys.self, forKey: .blogInfo)
          var nameKeys = blogInfoKeys.nestedContainer(keyedBy: NameKeys.self, forKey: .name)
          try nameKeys.encode(self.blogName, forKey: .first)
        }
      }​
  • 사용하는 쪽
class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    
    let myModel = MyModel(userID: "jake", blogName: "iOS 앱 개발 알아가기")
    guard let data = try? JSONEncoder().encode(myModel) else { return }
    let jsonString = String(data: data, encoding: .utf8)
    
    print(jsonString)
    /*
     {\"user_id\":\"jake\",\"blog_info\":{\"name\":{\"first\":\"iOS 앱 개발 알아가기\"}}}
     */
  }
}

* 전체 코드: https://github.com/JK0369/ExEncoding

Comments