STUDYING/iOS

[iOS] Codable에 관하여

EOZIN 2018. 11. 28. 09:45
728x90

Codable

Codable이란 ?

A type that can convert itself into and out of an external representation. - Apple Doc

외부 표현을 변환할때 사용한다.

  • 우리가 사용하는 이유는 JSON 데이터를 우리가 만들 애플리케이션에서 사용하기 편하도록 객체에 맵핑하기 위해 사용한다.

    • Decodable : 자신을 외부표현으로부터 디코딩할수있는 타입.

    • Encodable : 자신을 외부표현으로 인코딩 할수있는 타입.

  • JSON기준에서

    • 서버파트에서 JSON데이터를 보내 줄 것이고, 현재 나와있는 거의 모든 API들이 JSON으로 뿌려준다.

//JSONData
{
"a":"나는 a입니다.",
"b":"나는 b입니다."
}
//Codable로 구성된 모델
struct Sample: Codable{
   var a:String
   var b:String  
   
   enum CodingKeys: String, CodingKey {
       case a
       case c = "b"
   }
}

JSON을 Codable로 처리할 때, 밑줄 표기법을 낙타 표기법으로 바꾼다거나 JSON에 있는 이름과 완전히 다른 이름으로 사용하려면 CodingKey를 따로 정의하면 된다.

let sampleDecoding = try! JSONDecoder().decode(Sample.self, from: sampleData)

앞서 Codable 정의에서 설명한 것 처럼 우리는 외부 표현 , 즉 JSON을 우리 애플리케이션에서 사용하기위해서 Decoding해서 사용해야한다.

JSONDecoder 를 사용할 때 error를 검출하기 위해서 try 이를 사용한다.

(정확한 데이터를 사용한다면 강제언래핑 처럼 try! 를 사용, 옵셔널이라면 try? 를 사용하고 데이터를 사용할때 if let 문으로 옵셔널 해제를 해줘야한다.)


  • JSONData 가 바뀌었을 경우 ?

    JSONData 가 바뀌어 원래 지정했던 키가 없을 경우가 있으므로

    모델 구조체 자체에서 JSON데이터를 디코딩 해서 keyNotFound 에러를 처리할수있다.

    키와 값이 없을 경우를 미리 정해놓는 것

    import UIKit
    //바뀐 JSON데이터
    let sample1Data = """
    {
       "a": "aa"
    }
    """.data(using: .utf8)!

    //아까 설정한
    struct Sample: Codable{
       var a:String
       var c:String
       
       enum CodingKeys: String, CodingKey {
           case a = "a"
           case c = "b"
       }
       
       init(from decoder: Decoder) throws {
           let values = try decoder.container(keyedBy: CodingKeys.self)
         
           a = try values.decodeIfPresent(String.self, forKey: .a) ?? "값이없습니다."
           c = try values.decodeIfPresent(String.self, forKey: .c) ?? "값이없습니다."
       }
       
    }
    let data = try! JSONDecoder().decode(Sample.self, from: sample1Data)

    init(from decoder: Decoder)에 a 와 c 라는 key 값이 매핑 됬을 경우 를 처리 해놨다.

    JSON데이터에 key "a"값만 보내주고 있으므로 "c"값에 대한 처리가 필요하다.

    try 를 해서 error 즉 실패 했을 경우 "값이 없습니다"를 key의 value에 할당해서 보여주는것이다.


  • JSON Array

{
   "status": 200,
   "message": "모든 글 조회 성공",
   "data": [
      {
           "id": 11,
           "title": "글 제목2",
           "contents": "내용내용내용",
      },
      {
           "id": 20,
           "title": "10",
           "contents": "",
      }
  ]
}

위 JSON데이터 처럼 배열 형태의 데이터가 있을 때는

struct ArraySample : Codable {
   var status: Int
   var message: String
   var userData: [UserArray]
 
   enum CodingKeys: String, CodingKey {
       case status
       case message
       case userData = "userArray"
   }
   
}
struct UserArray : Codable {
   var id: Int
   var title: String
   var contents: String
   
}

let arraySampleDecoding = try! JSONDecoder().decode(ArraySample.self, from: arrayJSONData)
print(arraySampleDecoding)

이렇게 모델을 중첩해서 사용하면 된다.


[tip] 한번에 JSON객체 만들 수 있는 사이트 : www.json4swift.com