#36 使用 JSONDecoder 把 JSON 轉換成自訂型別的資料
練習目的:練習 JSON decode(iTunes、Dcard)
利用 JSON Editor Online 排版JSON 資料,可以更清楚看出分層:
iTunes 搜尋 swift 當例子,API 的網址為:
https://itunes.apple.com/search?term=swift&media=music
先分層JSON,JSON 對應的自訂型別,當 JSON 愈多層,愈多 { } 時,需要定義愈多的 struct
第一層資料:
有兩個key,分別是resultCount、result
struct 自訂第一層資料格式,命名為 SearchResponse,兩個參數型別格式、命名必須跟JSON回傳的一模一樣,results有50筆資料,用array儲存,命名為[StoreItem]
第二層資料:
results中的資料,沒有再包{},可知此JSON就兩層
struct 自訂第二層資料格式,命名為StoreItem,定義要抓的資料的key、型別格式,有些資料會是optional,有可能為nil,需加上?
解析 JSON 資料的方法(利用 JSONDecoder)
執行結果
程式說明:
- 不會卡住 UI 的下載方法,利用 URLSession,dataTask回傳抓資料的任務
dataTask(with:completionHandler:) 的 completionHandler
completionHandler: (Data?,URLResponse?, Error?) -> Void) ->
URLSessionDataTask
• data: 抓到的資料
• response: 後台回傳抓資料的相關結果
•error: 錯誤資訊
let urlString = "https://itunes.apple.com/search?term=swift&media=music&country=tw"if let url = URL(string: urlString){URLSession.shared.dataTask(with: url) { data, response, error in...
...
...}
2. JSONDecoder解碼的物件,把JSON的資料轉換成自訂型別
let decoder = JSONDecoder()
3. JSONDecoder 解析時間的 DateDecodingStrategy
decoder.dateDecodingStrategy = .iso8601
4. do catch:有可能會丟錯誤出來的程式可以用do catch寫
do{}:寫要試的內容
catch{}:有錯誤要跑到catch
do{let searchResponse = try decoder.decode(SerchResponse.self, from: data)
//呼叫decoder的function decode()
//要將資料變成什麼型別,由第一個參數決定,所以傳入要轉的型SerchResponse.self,型別本身要是資料需要加.selfprint(searchResponse.results[2].trackName)}catch{print(error)}
5. resume啟動
.resume()
完整程式碼:
Dcard當例子,API 的網址為:
目前無法直接連到 API 抓資料,若想測試可從 Safari 連到 API 網址,抓取 JSON 後將 JSON 貼到程式裡
多行字串JSON 解析,利用三個雙引號的多行字串包含 JSON 資料,然後呼叫 function data(using:) 得到 Data 型別的 JSON 資料,此時得到的資料就像我們利用 URLSessionTask 從網路下載的資料
****JSON字串變data,而不是從url****
let data = """...
...
...
"""..data(using: .utf8)!
第一層資料:
命名為PostResponse,定義要抓的資料的key、型別格式
第二層資料:
MediaMeta為array,命名為Media
解析 JSON 資料的方法(利用 JSONDecoder)
#由於JSON第一層為Array,所以在 decode 時傳入的型別加上 [ ] ,例如上方的[PostResponse]
執行結果