簡體   English   中英

Swift URLRequest 解析平台 REST API (JSON) 並解碼為 Struct

[英]Swift URLRequest to Parse Platform REST API (JSON) & Decode into Struct

我正在嘗試使用適用於 Parse 平台(服務器)的可用 iOS SDK 中不可用的特定功能,但我知道 REST API 可以使用這些功能。 專門用於使用 DISTINCT 查詢。

在我的開發計算機 (Rested.app) 上使用 Parse Dashboard 和 REST API 客戶端應用程序,我已驗證以下查詢按預期完成:

curl -X GET \
-H "X-Parse-Application-Id: someAppID" \
-H "X-Parse-Master-Key: someKey" \
-G \
--data-urlencode "distinct=TeeTime" \
http://somehost:1337/parse/aggregate/CompEntry

哪個成功返回數據:

{ "results": [ { "__type": "Date", "iso": "2020-08-29T07:00:00.000Z" }, { "__type": "Date", "iso": "2020-08 -29T07:09:00.000Z" } ] }

原始數據來自,有 3 行,其中 2 行共享相同的 TeeTime:

解析儀表板屏幕截圖

以及 Rested.app 輸出的屏幕截圖:

Rested.app 輸出截圖

現在我正在嘗試為我的 Swift/iOS 項目轉換它。

我正在嘗試使用 Codable/Decodable 方法並匹配 JSON 屬性名稱,將下載的數據移動到一個新的結構中來表示對象。 到目前為止,我擁有的代碼如下(也放置了一些內聯注釋)。 Struct 定義出現在單獨的 .swift 文件中,但只要在主 ViewController 定義之外。

struct TeeTimeData: Codable {
    let results: [Results]
}

struct Results: Codable {
    let __type: String
    let iso: String // TODO: THIS SHOULD BE A DIFFERENT DATA TYPE - I HAVE PICKED HARDER DATA TYPE TO START WITH!
}

然后在主 ViewController 結構中:

class ViewController: UIViewController {

    @IBAction func buttonGetTeeTimes(_ sender: UIButton) {
        
        if let url = URL(string: "http://somehost:1337/parse/aggregate/CompEntry") {
            var request = URLRequest(url: url)
            request.addValue("someAppID", forHTTPHeaderField: "X-Parse-Application-Id")
            request.addValue("someKey", forHTTPHeaderField: "X-Parse-Master-Key")
            request.httpMethod = "GET"
            let params = ["distinct": "TeeTime"] // TODO: THIS VAR IS NOT ACTUALLY BEING TIED TO THE REQUEST EITHER - 2nd PROBLEM...
            
            let session = URLSession(configuration: .default)
            
            let requestTask = session.dataTask(with: request) { (data, response, error) in
                
                if error != nil {
                    print("API Error: \(error)")
                }
                
                if let dataUnwrap = data {
                    // TODO: MOVE THIS INTO NEW CLASS (DataModel, etc)
                    let decoder = JSONDecoder()
                    
                    do {
                        let decodedData = try decoder.decode(TeeTimeData.self, from: dataUnwrap)
                        
                        print(decodedData)
                        
                    } catch {
                        print("Decode Error: \(error)")
                    }
                    
                    
                }
            }
            
            requestTask.resume()
            
        }
    }
}

控制台輸出是:

解碼錯誤:keyNotFound(CodingKeys(stringValue: "__type", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "results", intValue: nil), _JSONKey(stringValue: "Index 0", intValue : 0)], debugDescription: "沒有與鍵 CodingKeys(stringValue: "__type", intValue: nil) ("__type") 關聯的值,underlyingError: nil))

我的第一個猜測是屬性定義開頭的 2 個下划線“__type”?

@Larme 在對開篇帖子的評論中提供的答案。 來自@gcharita 的貢獻,如果我的語法與我正在執行的其他測試具有相同的結構(它不是 - 見下文),它應該可以工作。

發生錯誤是因為返回的結果是不同的 JSON 結構,因為未應用distinct=TeeTime過濾器。 所以它返回一個 JSON 對象,其中包含類中的所有數據行,而不是我的 TeeTimeData 結構對象中指定的數據行。

?distinct=TeeTime附加到 URL 字符串的末尾解決了問題並返回:

解碼數據:TeeTimeData(results: [Parse_2.Results(__type: "Date", iso: "2020-08-29T07:00:00.000Z"), Parse_2.Results(__type: "Date", iso: "2020-08 -29T07:09:00.000Z")])

這也意味着我不再需要let params = ["distinct": "TeeTime"]代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM