Utku Tarhan
Utku Tarhan

Reputation: 49

Parsing JSON from URL ends up with an Error - Swift 5

I am trying to write a function in swift that gets data from an URL JSON, and allocate it to variables in swift.

This is the function:

func getBikeData(){
    guard let url = URL(string: "https://api.citybik.es//v2/networks/baksi-bisim") else {return}
    let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
    guard let dataResponse = data,
              error == nil else {
              print(error?.localizedDescription ?? "Response Error")
              return }
        do{
            //here dataResponse received from a network request
            let jsonResponse = try JSONSerialization.jsonObject(with:
                                   dataResponse, options: [])
            print(jsonResponse) //Response result


            do {
                //here dataResponse received from a network request
                let decoder = JSONDecoder()
                //Decode JSON Response Data

                let model = try decoder.decode(Station.self,
                                               from: dataResponse)
                print(model.freeBikes) //Output - 1221

            } catch let parsingError {
                print("Error", parsingError)
            }
         } catch let parsingError {
            print("Error", parsingError)

       }
    }
    task.resume()

}

This is the struct's that I added, with the data I need:

    // MARK: - Station
struct Station: Codable {
    let emptySlots: Int
    let extra: Extra
    let freeBikes: Int
    let id: String
    let latitude, longitude: Double
    let name, timestamp: String

    enum CodingKeys: String, CodingKey {
        case emptySlots
        case extra
        case freeBikes
        case id, latitude, longitude, name, timestamp
    }
}

// MARK: - Extra
struct Extra: Codable {
    let slots: Int
    let status: Status
    let uid: String
}

enum Status: String, Codable {
    case active = "Active"
}

This is the error I have been receiving:

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

This is the first time I was working with a JSON file, and maybe I am missing something very simple. Please help.

Upvotes: 2

Views: 661

Answers (2)

elliott-io
elliott-io

Reputation: 1414

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

The above error will occur if you are trying to decode a JSON object that doesn't have that key and the key is not marked as an optional.

You can either fix the server-end so emptySlots is returned or mark emptySlots as an optional in your struct:

struct Station: Codable {
    let emptySlots: Int?

Upvotes: 1

Peter Schorn
Peter Schorn

Reputation: 987

Here is how to decode all the json data into a swift struct:

import Foundation


struct Stations: Codable {
    let company: [String]
    let href: String
    let id: String
    let location: LocationJson
    let name: String
    let stations: [Station]

}


struct Station: Codable {
    let empty_slots: Int
    let extra: Extra
    let free_bikes: Int
    let id: String
    let latitude: Double
    let longitude: Double
    let name: String
    let timestamp: String

}

struct ResponseJSON: Codable {
    let network: Stations
}

struct LocationJson: Codable {
    let city: String
    let country: String
    let latitude: Double
    let longitude: Double
}


struct Extra: Codable {
    let slots: Int
    let status: String
    let uid: String
}


func getBikeData(){
    guard let url = URL(
        string: "https://api.citybik.es//v2/networks/baksi-bisim"
    ) else { return }

    let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
        guard let dataResponse = data, error == nil else {
            print(error?.localizedDescription ?? "Response Error")
            return
        }
        do {
            //here dataResponse received from a network request
            let jsonResponse = try JSONSerialization.jsonObject(with:
                                   dataResponse, options: [])
            print(jsonResponse) //Response result


            do {
                //here dataResponse received from a network request
                let decoder = JSONDecoder()
                //Decode JSON Response Data

                let model = try decoder.decode(
                    ResponseJSON.self, from: dataResponse
                )
                print(model) //Output - 1221

            } catch let parsingError {
                print("Error", parsingError)
            }

         } catch let parsingError {
            print("Error", parsingError)
         }
    }
    task.resume()

}

getBikeData()

Upvotes: 1

Related Questions