관리 메뉴

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

[iOS - swift] codable을 이용한 json 파싱 본문

iOS 응용 (swift)

[iOS - swift] codable을 이용한 json 파싱

jake-kim 2020. 8. 30. 00:04

codable을 사용하여 json데이터를 가져오는 것

json자료형을 직접 파싱해서 사용하는 것은 코드상의 복잡함이 따름 -> 미리 struct형을 정해놓고 거기에 매핑되게끔하는 방법

 

case #1. 일반적인 사용방법


// json데이터 형태를 미리 정의
struct DataForm: Codable {
    var key_name1: String?
    var key_name2: String?
}

// json데이터
let sample = """
{
    "key_name1": "value1",
    "key_name2": "value2"
}
""".data(using: .utf8)!

// 결과
let result = try! JSONDecoder().decode(DataForm.self, from: sample)
print(result) // DataForm(key_name1: "value1", key_name2: "value2")

case #2. nil값이나 없는 값 처리 - 옵셔널로 선언 or decode사용


struct DataForm: Codable {
    var key_name1: String?
    var key_name2: String?
}

// 결과: // DataForm(key_name1: Optional("value1"), key_name2: Optional("value2"))
// 방법2: decode 사용

let sample = """
        {
            "key_name1": "value1"
        }
        """.data(using: .utf8)!

struct DataForm: Codable {
    var key_name1: String
    var key_name2: String

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        key_name1 = try values.decodeIfPresent(String.self, forKey: .key_name1) ?? "디폴트값1"
        key_name2 = try values.decodeIfPresent(String.self, forKey: .key_name2) ?? "디폴트값2"
    }
}

// DataForm(key_name1: "value1", key_name2: "디폴트값2")

case #3. struct형 변수이름과 JSON의 key값 이름이 다른경우 - CodingKeys사용


struct DataForm: Codable {
    var key_name1: String?
    var haha: String?

    enum CodingKeys: String, CodingKey {
        case key_name1, haha = "key_name2"
    }
}

case #4. 배열 파싱 - singleValueContainer로 구현


let sample = """
["a", "b", "c"]
""".data(using: .utf8)!

let result = try! JSONDecoder().decode(DataForm.self, from: sample)
print(result) // DataForm(arr: ["a", "b", "c"])

case #5. 리스트에  타입 다른 여러 값 파싱- init(from decoder: Decoder) 구현

let sample = """
["a", 1, 1.0, true]
""".data(using: .utf8)!

let result = try! JSONDecoder().decode(DataForm.self, from: sample)
print(result) // DataForm(str: "a", int: 1, double: 1.0, bool: true)

struct DataForm: Codable {

    var str: String
    var int: Int
    var double: Double
    var bool: Bool

    init(from decoder: Decoder) throws {
        var unkeyedContainder = try decoder.unkeyedContainer()
        str = try unkeyedContainder.decode(String.self)
        int = try unkeyedContainder.decode(Int.self)
        double = try unkeyedContainder.decode(Double.self)
        bool = try unkeyedContainder.decode(Bool.self)
    }
}

case #6. Response에 있는 객체 중, 여러개의 값을 가지는(enum)경우 파싱

// 서버에서는 “status”: “ODST000003”와 같이 내려주는 형태
// 처리: Response객체가 response라면,
// switch response.status {… } 일반 enum처리 하듯이 해서 처리

public struct Response: Codable {
    let id: Int
    let status: MyStatus
}

enum MyStatus: String, Codable {
    case status1 = "ODST000001"
    case status2 = "ODST000002"
    case status3= "ODST000003"
    case status4 = "ODST000004"
}

* Codable과 enum을 사용한 json 파싱 방법: ios-development.tistory.com/284

Comments