Search code examples
iosarraysjsonswiftjsondecoder

Error while trying to phrase JSON with Swift


I'm trying to receive data from a JSON link in Swift Playground on Mac, I've struct all the data, but I'm having issue trying to decode all of the data, receiving the error: "Referencing instance method 'decode(_:from:)' on 'Array' requires that 'Bicimia' conform to 'Decodable'"

I've already tries to add the Codable/Decodable option, and tried to change the URLSession respectively, but nothing has changed.

struct Bicimia {

    let network: Network

}


struct Network {

    let company: [String]
    let href, id: String
    let location: Location
    let name: String
    let stations: [Station]

}

struct Location {

    let city, country: String
    let latitude, longitude: Double

}

struct Station {

    let emptySlots: Int
    let extra: Extra
    let freeBikes: Int
    let id: String
    let latitude, longitude: Double
    let name, timestamp: String

}

struct Extra {

    let extraDescription: String
    let status: Status

}

enum Status {

    case online
}


let url = "https://api.citybik.es/v2/networks/bicimia"
let urlOBJ = URL(string: url)

URLSession.shared.dataTask(with: urlOBJ!) {(data, response, error) in


    do {
        let res = try JSONDecoder().decode([Bicimia].self, from: data!)
        print(res)
    }
    catch {
        print(error)
    }
}.resume()

Solution

  • To be Decodable all properties should be Decodable down the chain:

    struct Bicimia: Decodable {
        let network: Network // should be decodable
    }
    
    struct Network: Decodable {
        let company: [String]
        let href, id: String
        let location: Location // should be decodable
        let name: String
        let stations: [Station] // should be decodable
    }
    
    struct Location: Decodable {
        let city, country: String
        let latitude, longitude: Double
    }
    
    struct Station: Decodable {
        let emptySlots: Int
        let extra: Extra // should be decodable
        let freeBikes: Int
        let id: String
        let latitude, longitude: Double
        let name, timestamp: String
    }
    
    struct Extra: Decodable {
        let extraDescription: String
        let status: Status // should be decodable
    }
    
    enum Status: String, Decodable {
        case online
    }
    

    Note that enums can not be Decodable alone, because they should know what is the raw value, or you should manually decode them in decode function.