관리 메뉴

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

[iOS - swift] mock 데이터를 로컬에 json형식으로 저장 후 사용 방법 (decode, encode, Bundle.main.path) 본문

iOS 응용 (swift)

[iOS - swift] mock 데이터를 로컬에 json형식으로 저장 후 사용 방법 (decode, encode, Bundle.main.path)

jake-kim 2021. 6. 2. 23:26

JSON 내용, codable 모델 생성

  • 클라이언트에서 데이터를 받는 방법은 .swift파일 내에나 plist에 세팅하는 방법이 있지만, 일반적으로 웹에서 json파일을 받아서 사용하는 방법이 많으므로 mock데이터도 json파일로 이용
  • json 데이터 작성 : quicktype에서 생성하여, json 내용 입력 시 자동으로 codable로 변경되도록 이용
    • iamge데이터는 따로 assets을 추가하고 json에는 이미지 이름만 명시 (실제 데이터는 url 존재하지만 mock 용도)
// 입력한 json 
[
    {
        "name": "Jake",
        "address_info": {
            "contry": "한국",
            "city": "서울"
        },
        "image": "01"

    },
    {
        "name": "Bob",
        "address_info": {
            "contry": "한국",
            "city": "인천"
        },
        "image": "02"
    }
]
// 생성된 codable

// MARK: - WelcomeElement
struct WelcomeElement: Codable {
    let name: String
    let addressInfo: AddressInfo
    let image: String

    enum CodingKeys: String, CodingKey {
        case name
        case addressInfo = "address_info"
        case image
    }
}

// MARK: - AddressInfo
struct AddressInfo: Codable {
    let contry, city: String
}

typealias Welcome = [WelcomeElement]

xcode에 .json 파일 생성

  • cmd+N -> Strings File 선택 -> 

  • File.strings -> mock.json으로 변경 후 저장

  • 만들어진 .json 파일에 json내용 기입

  • "Target Membership"에서 체크
    • 체크되지 않은 상태가 default이고 체크되지 않으면 Bundle.main.path하여 해당 파일 불러오기가 불가

  • mock Assets 추가

  • Codable 모델 추가

JSON 파일 로드

  • path 추출
guard let path = Bundle.main.path(forResource: "mock", ofType: "json") else {
    return
}

print(path)
// /Users/jongkwon-kim/Library/Developer/CoreSimulator/Devices/69D31078-80C4-467D-8DB2-8642D70F4903/data/Containers/Bundle/Application/026A8EAA-8C7E-4BDA-8E10-27D78F600366/Test.app/mock.json
  • jsonString 추출
    • 주의: file이면 String(contentsOfFile:) 사용, 웹 url이면 String(contentsOf:) 사용
guard let jsonString = try? String(contentsOfFile: path) else {
    return
}
  • decode: String -> swift에서 정의한 모델
    • 주의: 배열이므로 [PersonModel].self이고 만약 객체이면 PersonModel.self로 사용
let decoder = JSONDecoder()
let data = jsonString.data(using: .utf8)
if let data = data,
   let person = try? decoder.decode([PersonModel].self, from: data) {
   print(person.first?.addressInfo) // Optional(Test.AddressInfo(contry: "한국", city: "서울"))
}
  • cf) encode 방법: swift에서 정의한 모델 -> jsonString
let dataModel = PersonModel(name: "sample", addressInfo: .init(contry: "contry", city: "city"), image: "03")
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(dataModel),
   let jsonString = String(data: jsonData, encoding: .utf8) {
    print(jsonString)
}

* 전체 코드

guard let path = Bundle.main.path(forResource: "mock", ofType: "json") else {
    return
}
guard let jsonString = try? String(contentsOfFile: path) else {
    return
}

let decoder = JSONDecoder()
let data = jsonString.data(using: .utf8)
if let data = data,
   let person = try? decoder.decode([PersonModel].self, from: data) {
    print(person.first?.addressInfo)
}

// MARK: - cf) Encode

let dataModel = PersonModel(name: "sample", addressInfo: .init(contry: "contry", city: "city"), image: "03")
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(dataModel),
   let jsonString = String(data: jsonData, encoding: .utf8) {
    print(jsonString)
}

* source code: https://github.com/JK0369/Mock_Json

Comments