Q:

Parsing a JSON file in Swift

I am new to Swift and I am having an issue with an application that I am developing. I am trying to parse some JSON provided by an API and I am encountering an issue where the program fails to decode the JSON into Swift Types provided by a struct. 
Recipe_API_Caller.swift
 import Foundation
 import UIKit

class call_Edamam_API{

func fetch(matching query: [String: String], completion: @escaping ([Recipe]?)-> Void){
        let baseURL = URL(string: "https://api.edamam.com/search")!

        guard let url = baseURL.withQueries(query)
            else{
                completion(nil)
                print("Cannot build URL")
                return
    }
    print(url)

        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in

            let Recipe_Decoder = JSONDecoder()

            if let data = data,

                let Recipes = try?
                    Recipe_Decoder.decode(Hit.self, from: data){

                completion(Recipes.hits)
            }
            else{
                print("JSON Decoding Error")
                completion(nil)
                return
            }
        }

        task.resume()

}
}

Recipe.swift
import Foundation
struct Hit: Codable{
    let hits: [Recipe]
}

struct Recipe: Codable{
    var name: String
    var image: URL
    var Ingredient_List: Array<String>
    var See_More_URL: URL

    enum Recipe_Coding_Keys: String, CodingKey{
        case name = "label"
        case image = "image"
        case Ingredient_List = "ingredientLines"
        case See_More_URL = "url"
    }

    init(from decoder: Decoder) throws {
        let recipe_Info = try decoder.container(keyedBy: Recipe_Coding_Keys.self)

        name = try recipe_Info.decode(String.self, forKey: Recipe_Coding_Keys.name)
        image = try recipe_Info.decode(URL.self, forKey: Recipe_Coding_Keys.image)
        Ingredient_List = try recipe_Info.decode(Array.self, forKey: Recipe_Coding_Keys.Ingredient_List)
        See_More_URL = try recipe_Info.decode(URL.self, forKey: Recipe_Coding_Keys.See_More_URL)

        print(name)
        print(See_More_URL)
    }
}

RecipeTableViewController.swift
import UIKit

class RecipeTableViewController: UITableViewController {

    @IBAction func downloadButtonTouched(_ sender: Any) {
    }

    let recipe_API_Call = call_Edamam_API()

    var returned_Recipes = [Recipe]()

    override func viewDidLoad() {
        super.viewDidLoad()
        print(searchTermImport)
        fetchRecipes()
    }

    func fetchRecipes(){
        self.returned_Recipes = []
        self.tableView.reloadData()

        let query: [String: String] = [
            "q": "Chicken",
            "app_id": "xxx",
            "app_key": "xxx"
        ]

        recipe_API_Call.fetch(matching: query, completion: {(returned_Recipes) in
            DispatchQueue.main.async {
                if let returned_Recipes = returned_Recipes{
                    self.returned_Recipes = returned_Recipes
                    self.tableView.reloadData()
                }
                else{
                    print("Fetch Error")
                }
            }
        })
    }

    func configureTable(cell: UITableViewCell, forItemAt indexPath: IndexPath){
        let returned_Recipe = returned_Recipes[indexPath.row]

        cell.textLabel?.text = returned_Recipe.name

        let network_task = URLSession.shared.dataTask(with: returned_Recipe.image){ (data, response, error)
            in
            guard let Image_dest = data else{
                return
            }
            DispatchQueue.main.async {
                let image = UIImage(data: Image_dest)
                cell.imageView?.image = image
            }
        }
        network_task.resume()
    }

    // MARK: - Table view data source

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return returned_Recipes.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "recipeCell", for: indexPath)

        // Configure the cell...
        configureTable(cell: cell, forItemAt: indexPath)
        return cell
    }

Part of JSON retrieved from URL
{
    "q" : "Chicken",
    "from" : 0,
    "to" : 10,
    "more" : true,
    "count" : 168106,
    "hits" : [ {
        "recipe" : {
            "uri" : "http://www.edamam.com/ontologies/edamam.owl#recipe_b79327d05b8e5b838ad6cfd9576b30b6",
            "label" : "Chicken Vesuvio",
            "image" : "https://www.edamam.com/web-img/e42/xxx.jpg",
            "source" : "Serious Eats",
            "url" : "http://www.seriouseats.com/recipes/2011/12/chicken-vesuvio-recipe.html",
            "shareAs" : "http://www.edamam.com/recipe/chicken-vesuvio-b79327d05b8e5b838ad6cfd9576b30b6/chicken",
            "yield" : 4.0,
            "dietLabels" : [ "Low-Carb" ],
            "healthLabels" : [ "Sugar-Conscious", "Peanut-Free", "Tree-Nut-Free" ],
            "cautions" : [ "Sulfites" ],
            "ingredientLines" : [ "1/2 cup olive oil", "5 cloves garlic, peeled", "2 large russet potatoes, peeled and cut into chunks", "1 3-4 pound chicken, cut into 8 pieces (or 3 pound chicken legs)", "3/4 cup white wine", "3/4 cup chicken stock", "3 tablespoons chopped parsley", "1 tablespoon dried oregano", "Salt and pepper", "1 cup frozen peas, thawed" ],

Upon running the app, the program receives data from the API call, but it is unable to decode it into Swift Types that I created in Recipe.swift. I receive the "JSON Decoding Error" that I created in Recipe_API_Caller.swift. I thought my issue may have been that I didn't have another struct for the "hits" part of the JSON file, but I added that and it is still giving me the error. 
I can print the created URL and input it into a web browser and browse the JSON file manually so I know my URL and API key are working properly. Xcode does not provide me with any official errors as to what is happening, so I am unsure of how to proceed from here. I would appreciate any advice that you all could provide! 

A:

The real problem with your code is the non-existent error handling when decoding, you need to rewrite that part so that it catches and prints any errors
if let data = data {
    do {
        let Recipes = try Recipe_Decoder.decode(Hit.self, from: data)
        completion(Recipes.hits)
    }
    else {
         print(error)
         completion(nil)
    }
}

If you change to this type of error handling you will get a lot of information from the error which in this case was

keyNotFound(Recipe_Coding_Keys(stringValue: "label", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "hits", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key Recipe_Coding_Keys(stringValue: \"label\", intValue: nil) (\"label\").", underlyingError: nil))

Which tells us that the decoder can't find the key "label" inside "hits" and this is because you are missing one level in your data structure for the key "recipe"

