Search code examples
jsonswiftalamofiredecodablejsondecoder

Data missing JSONDecoder


I am trying to load an array of JSON dictionaries into an object with swift using Alamofire and SwiftyJSON, but when the data is downloaded, I get the error:

keyNotFound(CodingKeys(stringValue: "inProrgresss", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"inProrgresss\", intValue: nil) (\"inProrgresss\").", underlyingError: nil)).

The localised description just says that the data is missing. My JSON is here and my code is like this:

struct CompData: Codable {
    let inProrgresss: [[String: String]]
    let past: [[String: String]]
    let upcoming: [[String: String]]
}

func getData(url: URLConvertible) {
    SVProgressHUD.show()
    Alamofire.request(url).responseJSON { (dataResponse) in
        if dataResponse.result.value != nil {
            SVProgressHUD.dismiss()
            let JSONVar = JSON(dataResponse.result.value)
            let data = Data(dataResponse.data!)
            print(data)
            let decoder = JSONDecoder()
            do {
                let newData = try decoder.decode(CompData.self, from: data)
                print("NEWDATA \(newData)")
            } catch {
                print(error)
            }
            print(JSONVar)
        }
    }
}

I am quite new to converting JSON into datatypes, and I couldn't find anything on here that helps.


Solution

  • Please read the JSON. There is no key inProrgresss.

    And create a struct for the dictionaries, it's pretty straightforward

    struct CompData: Decodable {
        let inProgress: [Location]?
        let past: [Location]
        let upcoming: [Location]
    }
    
    struct Location : Decodable {
        let city, countryCode, name, date, country, id : String
    }
    

    And declare inProgress as optional because the array is empty.

    Edit:

    There is a lot of redundant code in getData. This is more efficient. convertFromSnakeCase does what it says.

    func getData(url: URLConvertible) {
        SVProgressHUD.show()
        Alamofire.request(url).responseData { (response) in
            SVProgressHUD.dismiss()
            switch response.result {
            case .success(let data):
                let decoder = JSONDecoder()
                decoder.keyDecodingStrategy = .convertFromSnakeCase
                do {
                    let result = try decoder.decode(CompData.self, from: data)
                    print("NEWDATA \(result)")
                } catch {
                    print(error)
                }
            case .failure(let error): print(error)
            }
        }
    }