[Swift] JSON 인코딩과 디코딩

이정훈·2023년 2월 2일
1

Swift 파헤치기

목록 보기
2/12
post-thumbnail

❓ JSON이 뭐야??


위키백과에 나온 JSON의 정의는 다음과 같다.

JSON(JavaScript Object Notation)은 "키-값 쌍"으로 이루어진 데이터 오브젝트를 전달하기 위해 인간이 읽을 수 있는 텍스트를 사용하는 개방형 표준 포맷이다.

어플리케이션을 만들면서 거의 필수적으로 해야 하는것.. 바로 API 호출인데, 요즘은 거의 대부분 API 호출로 JSON 형식의 데이터를 받기 때문에 JSON 데이터를 다루는 것은 필수라고 생각된다.

추가적으로 어플리케이션의 데이터를 추가할 때도 JSON 형태로 사용할 수 있고..아무튼 많은 곳에서 사용이 된다.

Swift에서 JSON 데이터를 Encoding하고 Decoding하는 방법에 대해 알아보자!

✅ Codable protocol


JSON encoding과 decoding에 앞서 알아야 할 것이 바로 Codable protocol이다.

Apple document에는 다음과 같이 정의 되어 있다.

typealias Codable = Decodable & Encodable

정의 자체도 Decodable protocol과 Encodable protocol을 조합한 사용자 정의 타입인 것을 알 수 있다.

Decodable protocol과 Encodable protocol은 각각 디코딩과 인코딩을 가능하게 하는 protocol이며

Codable 타입을 준수하는 데이터는 Foundation framework에 정의 되어 있는 JSONDecoder, JSONEncoder를 통해 데이터를 디코딩, 인코딩 할 수 있다.

이제 실제로 데이터를 디코딩과 인코딩을 하는 법을 알아보자

💻 JSON data Encoding


먼저 JSON 데이터를 인코딩 하기 전에 파싱(parsing)을 위한 구조체를 먼저 정의한다.

예시로 유저 정보를 담기위한 구조체로 유저의 이름과 나이, e-mail, 자택 주소를 데이터로 가지는 구조체를 정의 했다.

import Foundation

struct Person: Codable {
    var name: String
    var age: Int
    var mail: String
    var address: String
}

인코딩과 디코딩에 사용될 타입은 반드시 Codable protocol을 채택할 것을 잊지 말자!

그리고 인코딩에 사용될 샘플 데이터를 아래와 같이 생성하였다.

let personKim: Person = Person(name: "김철수", age: 99, mail: "kim@mail.com", address: "서울특별시 종로구")
let personLee: Person = Person(name: "이영희", age: 20, mail: "lee@mail.com", address: "부산광역시 연제구")

이제 샘플 데이터를 JSON 데이터로 인코딩해 줄 차례이다.

func jsonEncoder(_ data: Codable) -> String? {
    var encoder = JSONEncoder()
    
    do {
        let jsonData = try encoder.encode(data)
        return String(data: jsonData, encoding: .utf8)
    } catch {
        print("encoding error")
    }
    
    return nil
}

먼저 JSONEncoder 인스턴스를 생성하기 위해서는 Foundation framework를 반드시 import 해야한다.

만약 잘못된 데이터를 받아 올 경우 오류를 피하기 위해 do-catch문으로 오류를 처리해 주었고 인코딩 실패에 대비하여 반환 타입 또한 optional 타입으로 정의 하였다.

그리고 콘솔 창에 JSON 데이터의 내용은 바로 출력이 되지 않기 때문에 JSON 데이터를 인코딩 후 String 타입으로 한번 더 인코딩 해 주었다.

여기서 String 타입 initializer의 parameter 내용은 다음과 같다.

init(data:encoding:)

  • data: String 타입으로 인코딩할 Data 타입의 전달인자를 받는다.
  • encoding: 인코딩 방식을 전달인자로 전달 받으며 해당 예시에서는 utf8 방식으로 인코딩 하였다.

JSON 인코딩으로 나온 결과 값은 다음과 같다.

print(jsonEncoder(personKim)!)
//{"age":99,"mail":"kim@mail.com","name":"김철수","address":"서울특별시 종로구"}

💻 JSON Decoding


조립은 분해의 역순이라는 말이 있다.

JSON 형식으로 인코딩된 데이터를 다시 디코딩 하는 방식은 인코딩의 역순으로 돌아가면 된다.

마찬가지로 JSON 데이터를 디코딩할 함수를 만들어 준다.

func jsonDecoder(_ data: String) -> Person? {
    var decoder = JSONDecoder()
    guard let jsonData = data.data(using: .utf8) else { return nil }    //Data type으로 디코딩
    
    do {
        let decoded: Person = try decoder.decode(Person.self, from: jsonData)
        return decoded
    } catch {
        print("decoding error")
    }
    
    return nil
}

아까 인코딩에서 반환한 String 타입의 데이터를 String 타입의 data method를 이용하여 다시 Data 타입으로 디코딩한다.

디코딩된 데이터를 JSONDecoder 인스턴스의 decode method를 이용하여 다시 Person 타입으로 디코딩한다.

decode method의 parameter 내용은 다음과 같다.

decode(_:from:)

  • 첫번째 매개변수로 변환(디코딩)할 타입이 전달
  • from 매개변수로는 디코딩할 데이터가 전달된다.

이렇게 디코딩된 결과 값은 다음과 같다.

let JSONData = jsonEncoder(personLee)!
let decoded = jsonDecoder(JSONData)
print(decoded!.name)    //이영희
profile
새롭게 알게된 것을 기록하는 공간

0개의 댓글