본문 바로가기
iOS/iOS

JSON ecdoing / decoding

by 패쓰킴 2022. 2. 24.
728x90

JSON encoding : 어떤 정보의 형태나 형식을 다른 형태나 형식으로 변환

JSON decoding : 인코딩의 반대 작업

 

우리는 인코딩과 디코딩을 위해 Encodable 또는 Decodable을 채택하여 인.디코딩을 진행하며,

이 두 작업과 동일한 기능을 'Codable'을 채택하여 진행 할 수 있다.

 

JSON 타입을 인.디코딩 하기위해 JSONEncoder 와 JSONDecoder를 사용한다.

(swift4 이전에는 JSONSerialization을 이용했었음.)

 

기본적인 인.디코딩 방법

JSONEncoder

struct Grocery: Codable {
    var name: String?
    var points: Int
    var importCountry: String?
}

var grocery = Grocery(name: "바나나", points: 20, importCountry: "필리핀")

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

do {
    let data = try encode.encode(grocery)
    print(String(data: data, encoding: .utf8)!)
} catch {
    print(error)
}


// 결과
{
  "name" : "바나나",
  "points" : 20,
  "importCountry" : "필리핀"
}

 

JSONDecoder

let json = """
{
    "name" : "바나나",
    "points" : 20,
    "importCountry" : "필리핀"
}
""".data(using: .utf8)!

let decode = JSONDecoder()

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


// 결과
바나나

 

직접 인.디코딩

우리는 값이 항상 들어오지 않는 객체가 있을 때면 '?'를 이용하여 옵셔널 처리를 해왔다.

 

직접 인디코딩을 해주어야 할때의 옵셔널 처리

class Grocery: Codable {
    var name: String?
    var points: Int
    var importContry: String?

    private enum CodingKeys: String, CodingKey {
      case name
      case points
      case importCountry
    }

    required init(from decoder: Decoder) throws {
        // container: 주어진 디코딩 할 키 데이터
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.name = try? container.decode(String.self, forKey: .name)
        self.points = try container.decode(Int.self, forKey: .points)
        self.importCountry = try? container.decode(String.self, forkey: .importCountry)
        
        /*
         try? container.decode(String.self, forkey: .importCountry)
         대신
         ((try container.decode(String?.self, forkey: .importCountry)) ?? ""
         해주어도 같은 결과값을 받을 수 있다.
        */
        
        
        /*
         만약, 상속 받은 슈퍼클래스가 있다면
         super.init(from: decoder)
         까지 작성해줄것!
        */
        
    }
}

json 디코딩을 해준다

(다른 외부라이브러리를 통해 디코딩 할 경우 불필요!)

let json = try! JSONDecoder().decode(Grocery.self, from: 만들어둔 jsonString data)

 

참고: https://zeddios.tistory.com/m/577

 

필드명 커스텀

API 통신 결과 JSON 데이터의 필드명이 맘에 안들때 원하는 이름을 지정하여 사용할 수 있다.

다음과 같은 response의 경우

{
  idx: 0
  addr: "주소"
}

CodingKey를 이용하여 원하는 이름과 필드명을 매치 시켜주면 Person.index 로 사용할 수 있도록 커스텀이 가능하다

struct Person: Codable {
  var index: Int
  var address: String
  
  enum CodingKeys: String, CodingKey {
    case index = "idx"
    case address = "addr"
  }
}
728x90

'iOS > iOS' 카테고리의 다른 글

UIView 값이 틀릴 때  (0) 2022.03.14
UIButton 상태에 따른 속성 적용(storyboard)  (0) 2022.02.24
CustomView  (0) 2022.02.23
ERROR 모음  (0) 2022.02.17
타이머  (0) 2022.01.25

댓글