2

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.

5
  • The coding keys enum is unnecessary unless the keys in the json dictionary differ from the instance variables in your Station struct. Creating a coding keys enum in which the raw values of all of the cases are the same as the case names is redundant. Commented May 5, 2020 at 2:43
  • The reason why you are getting the error is because the type of the data contained in your json object isn't even close to matching the type of the Station struct. Commented May 5, 2020 at 2:59
  • @PeterSchorn Thank you for your comment, I generated the code using quicktype.io JSON to swift structs. However, as you see there are too many data I don't really need. Is there a way to cherry-pick only needed data? Or should it be all included to interpret data accurately? Commented May 5, 2020 at 3:09
  • I don't know if it is possible to cherry pick only the data you need. Commented May 5, 2020 at 3:18
  • 1
    You should check out this library: github.com/SwiftyJSON/SwiftyJSON Commented May 5, 2020 at 11:35

2 Answers 2

1

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()
Sign up to request clarification or add additional context in comments.

Comments

1
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?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.