迅速5问题中的“预期对array <any>进行解码,但找到了字典”

时间:2019-12-03 15:36:16

标签: arrays json swift api

我正在尝试从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
}

2 个答案:

答案 0 :(得分:1)

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

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

第二个使用新的Result API才能在同一对象中返回结果和错误

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)
    }
}

答案 1 :(得分:0)

看来您的完成处理程序无效。

此代码有效:

let data = """
{
   "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
}
""".data(using: .utf8)!
class decodeRecipe: Codable {
    struct response: Codable {
        struct result: Codable {
            var id: Int?
            var title: String?
            var image: String?
            var readyInMinutes: Int?
            }
        var results: [result] = []
    }
}
do {
let res = try JSONDecoder().decode(decodeRecipe.response.self, from: data)
    print(res)
} catch {
    print(error)
}

结果:

  

响应(结果:[__lldb_expr_13.decodeRecipe.response.result(id:   可选(485365),标题:可选(“鸡菠菜–面包屑   酿的鸡胸肉配菠菜,西兰花和奶酪”),图片:   可选(“鸡肉菠菜面包夹心鸡胸配菠菜西兰花和奶酪-485365.jpg”),readyInMinutes:可选(65))))

但是您呼叫的completed([])不是@escaping(decodeRecipe.response) -> Void?

我建议返回nilcompleted(nil)而不是空数组。

并使用@escaping(decodeRecipe.response?) -> Void?

顺便说一句,使用大写字母作为每种类型名称的首字母。