首页 > 解决方案 > “预计解码数组但在 swift 5 问题中找到了字典

问题描述

我正在尝试从 API 接收数据,我可以将其作为字符串接收,但是当我尝试将其放入数组或列表时,它现在不起作用,这是我的代码。

这是模型

class DecodeRecipe: Codable {
    struct Response: Codable {
        struct Result: Codable {
            var id: Int?
            var title: String?
            var image: String?
            var readyInMinutes: Int?
            }
        var results: [result] = []
    }
}

这是从 API 接收字符串的代码

class APIRequest {
    static let instance = APIRequest()
    var query: String = ""
    var url: String = ""
    var testString: String = ""

    func setURL(_ url: String) -> Void { 
        self.url = url
    }

    func setQuery(_ query: String) -> Void {
        self.query = query
    }

    func getReturn(completed: @escaping(decodeRecipe.response) -> Void?) {
        // TODO MAJOR!
        // Expressions are not allowed at top level will occur otherwise
        //

            let headers = [
                "x-rapidapi-host": "spoonacular-recipe-food-nutrition-v1.p.rapidapi.com",
                "x-rapidapi-key": "e44daac5e0mshc682df24497a89fp1c4513jsn7067934f0b9b"
            ]

            let request = NSMutableURLRequest(url: NSURL(string: "https://spoonacular-recipe-food-nutrition-v1.p.rapidapi.com/recipes/search?number=1&query=\(query)")! as URL,
                                                    cachePolicy: .useProtocolCachePolicy,
                                                timeoutInterval: 10.0)
            request.httpMethod = "GET"
            request.allHTTPHeaderFields = headers

            let session = URLSession.shared
        var myStruct = decodeRecipe.response.result()
            let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
                if (error != nil) {
                    print(error!)
                } else {
                    if let data = data, let dataString = String(data: data, encoding: .utf8) {
                        myStruct.title = dataString

                        do{
                            print(dataString)
                            let decoder = try JSONDecoder().decode(decodeRecipe.response.self, from: data)
                            completed(decoder)
                        }
                        catch{
                            print(error)
                            completed([])
                        }
                    }
                }
            })
            dataTask.resume()
        }
    }

希望对此做出一些回应。问题可能是结构的结构,但我不确定该怎么做

示例 JSON 响应

{
   "results":[
      {
         "id":485365,
         "title":"Chicken Spinoccoli – Breaded Stuffed Chicken Breast With Spinach, Broccoli and Cheese",
         "readyInMinutes":65,
         "servings":4,
         "image":"chicken-spinoccoli-breaded-stuffed-chicken-breast-with-spinach-broccoli-and-cheese-485365.jpg",
         "imageUrls":[
            "chicken-spinoccoli-breaded-stuffed-chicken-breast-with-spinach-broccoli-and-cheese-485365.jpg"
         ]
      }
   ],
   "baseUri":"https://spoonacular.com/recipeImages/",
   "offset":0,
   "number":1,
   "totalResults":326,
   "processingTimeMs":361,
   "expires":1575604426682,
   "isStale":false
}

标签: arraysjsonswiftapi

解决方案


首先,封闭类DecodeRecipe是多余的。省略它。并将所有结构成员声明为常量

struct Response: Codable {
    struct Result: Codable {
        let id: Int
        let title: String
        let image: String
        let readyInMinutes: Int
    }
    let results: [Result]
}

其次,使用新的ResultAPI 能够在同一个对象中返回结果和错误

class APIRequest {
    static let instance = APIRequest()

    var query: String = ""
    var url: String = ""
    var testString: String = ""

    func getReturn(completed: @escaping (Result<Response, Error>) -> Void) {
        // TODO MAJOR!
        // Expressions are not allowed at top level will occur otherwise
        //

        let headers = [
            "x-rapidapi-host": "spoonacular-recipe-food-nutrition-v1.p.rapidapi.com",
            "x-rapidapi-key": "e44daac5e0mshc682df24497a89fp1c4513jsn7067934f0b9b"
        ]

        var request = URLRequest(url: URL(string: "https://spoonacular-recipe-food-nutrition-v1.p.rapidapi.com/recipes/search?number=1&query=\(query)")!,
                                 cachePolicy: .useProtocolCachePolicy,
                                 timeoutInterval: 10.0)
        request.httpMethod = "GET"
        request.allHTTPHeaderFields = headers

        let session = URLSession.shared
        let dataTask = session.dataTask(with: request) { (data, response, error) -> Void in
            if let error = error { completed(.failure(error));  return }
            do {
                let result = try JSONDecoder().decode(Response.self, from: data!)
                completed(.success(result))
            } catch {
                completed(.failure(error))
            }
        }
        dataTask.resume()
    }
}

并称之为

let request = APIRequest.instance
request.query = "Pizza"
request.getReturn { result in
    switch result {
        case .success(let result): print(result)
        case .failure(let error): print(error)
    }
}

推荐阅读