티스토리 뷰

[iOS]/ㄴSwift

[Swift] JSON 사용하기1

__hyeon2__ 2022. 6. 14. 01:42
728x90
반응형

 

애플 공식문서 Using JSON with Custom Types에 나온 예제를 공부하고 정리한 글입니다.
 오타 시정 및 피드백은 언제나 환영입니다 🥰


1. 배열에서 데이터 읽어오기 (Read Data From Arrays)

 

👀 전체 코드 먼저 보기

import Foundation

let json = """
[
    {
        "name": "Banana",
        "points": 200,
        "description": "A banana grown in Ecuador."
    },
    {
        "name": "Orange",
        "points": 100
    }
]
""".data(using: .utf8)!

struct GroceryProduct: Codable {
    var name: String
    var points: Int
    var description: String?
}

let decoder = JSONDecoder()
let products = try decoder.decode([GroceryProduct].self, from: json)

for product in products {
    print("""
    name : \(product.name)
    points: \(product.points)
    """)
    if let description = product.description {
        print("description: \(description) \n")
    }
}

/*
<print 결과>
name : Banana
points: 200
description: A banana grown in Ecuador. 

name : Orange
points: 100
*/

 

🖍 코드 설명

import Foundation

JSONDecoder 클래스의 인스턴스를 생성하려면  Foundation 프레임워크를 추가해야 합니다.

 

안 그럼 아래 같은 오류가..!


let json = """
[
    {
        "name": "Banana",
        "points": 200,
        "description": "A banana grown in Ecuador."
    },
    {
        "name": "Orange",
        "points": 100
    }
]
""".data(using: .utf8)!

더미 데이터가 담긴 상수 json을 선언해줍니다.

data(using: . utf8) 메서드는 인코딩 된 더미 데이터 객체를 Data 타입으로 반환합니다.  

Data 타입으로 반환하는 이유는 뒤에 decode 메서드 사용 시, Data 타입의 인수가 필요하기 때문입니다.


struct GroceryProduct: Codable {
    var name: String
    var points: Int
    var description: String?
}

사용하는 json의 키값을 프로퍼티로 가지고, Codable 프로토콜을 채택하는 구조체를 만들어줍니다. 

 

위 예시에서 json이란 상수가  name, points, description을 키 값으로 갖고 있으므로 이 키값을 변수명으로 선언해줍니다.

이때, description은 있을 때도 있고 없을 때도 있으므로 옵셔널 타입으로 선언합니다.

 

여기서 잠깐!

Codable이란, Decodable 프로토콜Encodable 프로토콜을 가리키는 별칭입니다!

(공식 문서에 들어가면 typealias 키워드를 사용하고 있죠😊)

애플 공식문서 발췌

 

그럼 Decodable 프로토콜과 Encodable 프로토콜이 뭘까요? 🤔

Decodable 프로토콜외부 표현에서 자신을 디코딩할 수 있는 유형이고,

Encodable 프로토콜외부 표현으로 자신을 인코딩할 수 있는 유형입니다.

 

즉, 데이터 인코딩 및 디코딩에 대한 표준화된 접근 방식을 정의한 것으로

이 프로토콜들을 채택하면 Encoder Decoder프로토콜의 구현이 데이터를 가져와

JSON 또는 프로퍼티 리스트와 같은 외부 표현으로 인코딩하거나 디코딩할 수 있습니다.

 

(왜 한국말이 더 어려운 것 같죠..?ㅎ)

 

아무튼 이름처럼 인코딩이나 디코딩을 할 수 있게 해주는 프로토콜이라 생각하면 될 것 같아요!

 

그래서 GroceryProduct 구조체는 Codable을 채택하고 있으므로 자동으로 디코딩이 가능하게 됩니다.


let decoder = JSONDecoder()
let products = try decoder.decode([GroceryProduct].self, from: json)

디코딩을 해주기 위해 JSONDecoder의 인스턴스를 생성해줍니다.

그다음 decode 메서드를 통해 디코딩이 된 값을 상수 products에 담아줍니다. 

 

공식문서에서 볼 수 있듯이, decode 메서드가 에러를 던지고 있으므로 에러 처리를 해줘야 합니다. 

디코딩할 유형을 [GroceryProduct]로 선언한 이유는 상수 json이 배열로 감싸져 있기 때문입니다.

(예제 코드에서는 배열 전체를 디코딩 또는 인코딩하려면 [Element] 구문을 사용하라고 합니다.)

 

만약, 상수 json이 다음과 같은 형태라면 배열로 선언해주지 않아도 됩니다.

let json = """
{
        "name": "Banana",
        "points": 200,
        "description": "A banana grown in Ecuador."
}

""".data(using: .utf8)!

// ... 중간 코드 생략

let products = try decoder.decode(GroceryProduct.self, from: json)

print(products)

/*
<print 결과>
GroceryProduct(name: "Banana", points: 200, description: Optional("A banana grown in Ecuador."))
*/
728x90
반응형
댓글