串接第三方 API,解析 JSON 資料,轉換成自訂型別顯示
目的
學習利用 URLSession 抓取後台的 JSON 資料,利用 JSONDecoder 和 Codable 將 JSON 資料生成自訂型別。
流程
以 iTunes 搜尋 Taylor Alison Swift 當例子,API 的網址為
https://itunes.apple.com/search?term=TaylorAlisonSwift&media=music
後台回傳的資料利用網站 JSON Editor Online 顯示後如下:
依照 iTunes 回傳的 JSON 可以看出資料架構,第一層是 object,object key results 的資料是 array,array 裡裝了許多歌曲 object。
因此定義了型別 SearchResponse 對應第一層的 object, StoreItem對應歌曲的object,並將 property results 的型別宣告為 [StoreItem],說明它是 array。
這裏將 SearchResponse & StoreItem 分開定義:
struct SearchResponse:Codable {
let resultCount: Int
let results: [StoreItem]
}
struct StoreItem:Codable {
let artistName: String
let trackName:String // 曲名
let collectionName:String? // 專輯名稱
let previewUrl:URL
let artworkUrl100:URL // image url
let trackPrice:Double? // 價錢
let releaseDate:Date
let isStreamable:Bool?
}
其中,StoreItem依照回傳值來設定參數型別,部分 property 被宣告為 optional,因為 JSON 裡有些 key 不會每一筆資料都有,像是trackPrice,不是每首歌都可以買,所以不一定有 trackPrice。因此將不一定會有的 collectionName、trackPrice 及isStreamable 設為 optional。如果沒有設為 optional,到時候一旦發現沒有這些欄位,將造成轉換失敗。
從回傳的資料得知時間格式採用 iso8601
獲取回傳資料:
func fetchItem(searchString:String) {
if let urlStr = "https://itunes.apple.com/search?term=\(searchString)&media=music".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), // 如果是中文字,需要轉成%形式
let url = URL(string: urlStr) {
URLSession.shared.dataTask(with: url) { (data, response , error) in
//利用 JSONDecoder 的 function decode 將 Data 型別的 JSON 資料變成型別 SearchResponse 的資料
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601 // 設定時間格式
if let data = data {
do {
let searchResponse = try decoder.decode(SearchResponse.self, from: data)
self.items = searchResponse.results
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch {
print("error")
}
} else {
print("error")
}
}.resume()
}
}
先使用URLSession.shared.dataTask建立從網路抓取資料的任務,呼叫resume()執行此任務,取得data後再利用 JSONDecoder 的 function decode 將 Data 型別的 JSON 資料轉換成自定義型別 “SearchResponse” 的資料。
在 StoryBoard 建立一個 TableViewController 用以顯示音樂清單:
TableViewCell使用自訂格式:
import UIKit
class MusicListTableViewCell: UITableViewCell {
@IBOutlet weak var trackImageView: UIImageView!
@IBOutlet weak var musicNameLabel: UILabel!
@IBOutlet weak var musicPriceLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
顯示音樂清單結果如下: