I'm working on a creative project, and I'm trying to decode content from an API database using Swift's JSONDecoder() function. I've built my structs, a getData() function, and I've set up a do-try-catch for the JSONDecoder() function. I'm having difficulty understanding what I'm doing to get the error I'm getting.
Here are my structs:
struct Response: Codable {
let foundRecipes: [Recipe]
let foundIngredients: [Ingredient]
}
struct Recipe: Codable {
let id: Int
let title: String
let image: String
let imageType: String
let usedIngredientCount: Int
let missedIngredientCount: Int
let missedIngredients: [Ingredient]
let usedIngredients: [Ingredient]
let unusedIngredients: [Ingredient]
let likes: Int
}
struct Ingredient: Codable {
let id: Int
let amount: Int
let unit: String
let unitLong: String
let unitShort: String
let aisle: String
let name: String
let original: String
let originalString: String
let origianalName: String
let metaInformation: [String]
let meta: [String]
let image: String
}
Here's my getData() function:
func getData(from url: String) {
URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { data, response, error in
guard let data = data, error == nil else {
print("something went wrong.")
return
}
var result: Response?
do {
result = try JSONDecoder().decode(Response.self, from: data)
}
catch {
print("")
print(String(describing: error)) // Right here is where the error hits.
}
guard let json = result else {
return
}
print(json.foundRecipes)
}).resume()
}
Here's a link to the API's documentation. The URL I'm calling in getData() links to the same structure of search as shown in their example: https://spoonacular.com/food-api/docs#Search-Recipes-by-Ingredients — and here's a screenshot of the url results for the exact search I'm working on: https://i.sstatic.net/MVtES.jpg
And finally, here's the full error that I'm catching:
typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil))
My understanding of this error is that it's saying I told the JSONDecoder() to look for a Dictionary of <String, Any>, but it's at the link and only seeing an array. I'm confused, because I don't know where it thinks I'm providing a dictionary. Where am I screwing up? Not looking for specific code changes, just some guidance on what I'm missing.
Thanks in advance :)
As you can see in your image of the API data and in the API documentation you linked to, the API is returning an array (in the documentation, for example, you can see that it is surrounded by [...]
). In fact, it looks like the API returns an array of Recipe
.
So, you can change your decoding call to this:
var result: [Recipe]?
do {
result = try JSONDecoder().decode([Recipe].self, from: data)
print(result)
} catch {
print(error)
}
Perhaps your idea for Response
came from somewhere else, but the keys foundRecipes
or foundIngredients
don't show up in this particular API call.
Also, thanks to @workingdog's for a useful comment about changing amount
to a Double
instead of an Int
in your model.