Codable 직접 사용해보기

고라니·2023년 8월 2일
0

TIL

목록 보기
19/67

이번에 Codable과 JSON에 대해 알아보았다, 그래서 직접 사용해보기로 했고 최근에 테이블뷰로 만들었던 음원 순위 프로젝트의 더미파일을 JSON으로 데체해보았다.

즉 기본 더미데이터를 인코딩하여 JSON형식으로 바꾸고 JSON파일로 만들어서 다시 디코딩하여 사용할 계획

음원 순위 화면

이전에 만들었던 뷰.
각 셀에 미리 작성한 더미파일의 데이터를 각 셀에 할당하여 표현했다.

struct Track: Codable {
    let rank: Int
    let albumImageName: String
    let titleText: String
    let author: String
    let description: String?

    var albumImage: UIImage? {
        return UIImage(named: albumImageName)
    }

    var subText: String {
        return [author, description].compactMap { $0 }.joined(separator: " ")
    }
}

extension Track {
    static let tracks: [Track] = [
        Track(rank: 5,
              albumImageName: "1집 Alone",
              titleText: "헤어지자 말해요",
              author: "박재정",
              description: nil),

        Track(rank: 1,
              albumImageName: "NewJeans 2nd EP 'Get Up'",
              titleText: "Super Shy",
              author: "NewJeans",
              description: nil),

        Track(rank: 9,
              albumImageName: "Steal The Show (From \"엘리멘탈\")",
              titleText: "Steal The Show",
              author: "Lauv",
              description: "(from \"엘리멘탈\")"),

        Track(rank: 6,
              albumImageName: "I've IVE",
              titleText: "I AM",
              author: "IVE (아이브)",
              description: nil),

        Track(rank: 2,
              albumImageName: "Seven(feat.Latto)- Clean Ver.",
              titleText: "Seven",
              author: "정국",
              description: "(feat.Latto) - Clean Ver."),

        Track(rank: 8,
              albumImageName: "MY WORLD - The 3rd Mini Album",
              titleText: "Spicy",
              author: "easpa",
              description: nil),

        Track(rank: 4,
              albumImageName: "I feel",
              titleText: "퀸카",
              author: "(여자)아이들",
              description: "(Queencard)"),

        Track(rank: 11,
              albumImageName: "UNFORGIVEN",
              titleText: "UNFORGIVEN",
              author: "LE SEERAFIM (르세라핌)",
              description: "(feat. Nile Rodgers)"),

        Track(rank: 10,
              albumImageName: "NewJeans 2nd EP 'Get Up'",
              titleText: "New Jeans",
              author: "NewJeans",
              description: nil),

        Track(rank: 7,
              albumImageName: "UNFORGIVEN",
              titleText: "이브, 프시케 그리고 푸른 수염의 아내",
              author: "LE SSERAFIM (르세라핌)",
              description: nil),

        Track(rank: 13,
              albumImageName: "NewJeans 1st Ep \"New Jeans\"",
              titleText: "Hype boy",
              author: "NewJeans",
              description: nil),

        Track(rank: 3,
              albumImageName: "NewJeans 2nd EP 'Get Up'",
              titleText: "ETA",
              author: "NewJeans",
              description: nil),

        Track(rank: 12,
              albumImageName: "I've IVE",
              titleText: "Kitsch",
              author: "IVE (아이브)",
              description: nil)
    ]
}

JSON 파일로 더미데이터의 역할을 대체할 것이기 때문에 나중에 삭제

Encoding

더미데이터를 인코딩한다.

let jsonEncoder = JSONEncoder()

do {
	let jsonData = try jsonEncoder.encode(tracks)
    if let jsonString = String(data: jsonData, encoding: .utf8) {
    	print(jsonString)
	}
} catch {
	print(error)
}

문자로 확인하기 위해 String으로 변환해 주었다.

결과는?

[{"author":"NewJeans","rank":1,"albumImageName":"NewJeans 2nd EP 'Get Up'","titleText":"Super Shy"},{"description":"(feat.Latto) - Clean Ver.","author":"정국","rank":2,"albumImageName":"Seven(feat.Latto)- Clean Ver.","titleText":"Seven"},{"author":"NewJeans","rank":3,"albumImageName":"NewJeans 2nd EP 'Get Up'","titleText":"ETA"},{"description":"(Queencard)","author":"(여자)아이들","rank":4,"albumImageName":"I feel","titleText":"퀸카"},{"author":"박재정","rank":5,"albumImageName":"1집 Alone","titleText":"헤어지자 말해요"},{"author":"IVE (아이브)","rank":6,"albumImageName":"I've IVE","titleText":"I AM"},{"author":"LE SSERAFIM (르세라핌)","rank":7,"albumImageName":"UNFORGIVEN","titleText":"이브, 프시케 그리고 푸른 수염의 아내"},{"author":"easpa","rank":8,"albumImageName":"MY WORLD - The 3rd Mini Album","titleText":"Spicy"},{"description":"(from \"엘리멘탈\")","author":"Lauv","rank":9,"albumImageName":"Steal The Show (From \"엘리멘탈\")","titleText":"Steal The Show"},{"author":"NewJeans","rank":10,"albumImageName":"NewJeans 2nd EP 'Get Up'","titleText":"New Jeans"},{"description":"(feat. Nile Rodgers)","author":"LE SEERAFIM (르세라핌)","rank":11,"albumImageName":"UNFORGIVEN","titleText":"UNFORGIVEN"},{"author":"IVE (아이브)","rank":12,"albumImageName":"I've IVE","titleText":"Kitsch"},{"author":"NewJeans","rank":13,"albumImageName":"NewJeans 1st Ep \"New Jeans\"","titleText":"Hype boy"}]

내가 알던 JSON 맞나? 읽기편하다고 했는데 읽기 불가능하다.

해결방법은 outputFormatting을 이용하는 것이다.
인코딩된 JSON 데이터의 출력 형식을 지정하는 역할을 한다.

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

코드를 추가하고 다시 확인

[
{
"author" : "NewJeans",
"rank" : 1,
"albumImageName" : "NewJeans 2nd EP 'Get Up'",
"titleText" : "Super Shy"
},
{
"description" : "(feat.Latto) - Clean Ver.",
"author" : "정국",
"rank" : 2,
"albumImageName" : "Seven(feat.Latto)- Clean Ver.",
"titleText" : "Seven"
},
{
"author" : "NewJeans",
"rank" : 3,
"albumImageName" : "NewJeans 2nd EP 'Get Up'",
"titleText" : "ETA"
},
{
"description" : "(Queencard)",
"author" : "(여자)아이들",
"rank" : 4,
"albumImageName" : "I feel",
"titleText" : "퀸카"
},
{
"author" : "박재정",
"rank" : 5,
"albumImageName" : "1집 Alone",
"titleText" : "헤어지자 말해요"
},
{
"author" : "IVE (아이브)",
"rank" : 6,
"albumImageName" : "I've IVE",
"titleText" : "I AM"
},
{
"author" : "LE SSERAFIM (르세라핌)",
"rank" : 7,
"albumImageName" : "UNFORGIVEN",
"titleText" : "이브, 프시케 그리고 푸른 수염의 아내"
},
{
"author" : "easpa",
"rank" : 8,
"albumImageName" : "MY WORLD - The 3rd Mini Album",
"titleText" : "Spicy"
},
{
"description" : "(from \"엘리멘탈\")",
"author" : "Lauv",
"rank" : 9,
"albumImageName" : "Steal The Show (From \"엘리멘탈\")",
"titleText" : "Steal The Show"
},
{
"author" : "NewJeans",
"rank" : 10,
"albumImageName" : "NewJeans 2nd EP 'Get Up'",
"titleText" : "New Jeans"
},
{
"description" : "(feat. Nile Rodgers)",
"author" : "LE SEERAFIM (르세라핌)",
"rank" : 11,
"albumImageName" : "UNFORGIVEN",
"titleText" : "UNFORGIVEN"
},
{
"author" : "IVE (아이브)",
"rank" : 12,
"albumImageName" : "I've IVE",
"titleText" : "Kitsch"
},
{
"author" : "NewJeans",
"rank" : 13,
"albumImageName" : "NewJeans 1st Ep \"New Jeans\"",
"titleText" : "Hype boy"
}
]

이제 예상했던 구조로 출력된다.

JSON 파일 만들고 Assets에 저장

JSON파일을 만드는 방법은 여러가지가 있지만, 기본 텍스트 편집기를 이용하여 .json확장자로 저장한다.

그리고 복제한 새로운 프로젝트의 Assets에 저장한다.

그런데 인코딩 할때도 보였고, 지금도 보이는 UTF-8이 뭘까?

UTF-8
UTF-8은 '유니코드 텍스트 변환 형식-8비트(Unicode Transformation Format)'을 의미하며, 유니코드 문자를 바이트로 인코딩하는 방법 중 하나이다.
즉 UTF-8은 컴퓨터가 데이터를 처리하는 방식인 이진법으로 된 정보들을 문자로 매핑하는 규칙 중 하나이다. 웹에서 많이 쓰이며 특히 JSON도 UTF-8을 이용하여 인코딩, 디코딩 한다.

UTF-8은 "유니코드 텍스트 변환 형식-8비트"을 의미하며, 유니코드 문자를 바이트로 인코딩하는 방법 중 하나입니다.

Decoding

메인 뷰컨트롤러에서 저장하던 Tracks는 주석처리하거나 삭제하고 빈 배열인 tracks를 새로 생성해준다.

    var tracks: [Track] = []
//    let tracks: [Track] = Track.tracks.sorted { $0.rank < $1.rank }

기존 더미데이터 모델인 Track은 지워주고 JSON으로 부터 데이터를 받아 인스턴스 생성을 위한 구조체를 새로 정의해준다.
description처럼 받아올 JSON파일에 값이 있는경우와 없는경우가 있따면 옵셔널타입으로 정의해준다.

struct Track: Codable {
    let author: String
    let rank: Int
    let albumImageName: String
    let titleText: String
    let description: String?

    var albumImage: UIImage? {
        return UIImage(named: albumImageName)
    }

    var subText: String {
        return [author, description].compactMap { $0 }.joined(separator: " ")
    }
}

인코딩 코드 대신 디코딩 코드를 작성한다.
NSDataAsset으로 ASSets에 있는 JSON을 생성하고 [Track] 으로 디코딩 하여 tracks에 저장한다.

let jsonDecoder = JSONDecoder()
        guard let dataAsset: NSDataAsset = NSDataAsset(name: "Tracks") else {
            return
        }
        do {
            tracks = try jsonDecoder.decode([Track].self, from: dataAsset.data)
        } catch {
            print(error)
        }

결과 확인

기존 더미데이터가 없어도 JSON데이터를 이용하여 이전과 동일한 뷰가 구현되었다.

profile
🍎 무럭무럭

0개의 댓글