이번에 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 파일로 더미데이터의 역할을 대체할 것이기 때문에 나중에 삭제
더미데이터를 인코딩한다.
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파일을 만드는 방법은 여러가지가 있지만, 기본 텍스트 편집기를 이용하여 .json확장자로 저장한다.
그리고 복제한 새로운 프로젝트의 Assets에 저장한다.
그런데 인코딩 할때도 보였고, 지금도 보이는 UTF-8이 뭘까?
UTF-8
UTF-8은 '유니코드 텍스트 변환 형식-8비트(Unicode Transformation Format)'을 의미하며, 유니코드 문자를 바이트로 인코딩하는 방법 중 하나이다.
즉 UTF-8은 컴퓨터가 데이터를 처리하는 방식인 이진법으로 된 정보들을 문자로 매핑하는 규칙 중 하나이다. 웹에서 많이 쓰이며 특히 JSON도 UTF-8을 이용하여 인코딩, 디코딩 한다.
UTF-8은 "유니코드 텍스트 변환 형식-8비트"을 의미하며, 유니코드 문자를 바이트로 인코딩하는 방법 중 하나입니다.
메인 뷰컨트롤러에서 저장하던 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데이터를 이용하여 이전과 동일한 뷰가 구현되었다.