Search code examples
jsonswiftdecodableticketmaster

How to use ticketmaster API in swift


This is the first time I have tried to use an API, I get the error "keyNotFound" Could someone point me in the right direction for understanding this better? Here is a link to their documentation: https://developer.ticketmaster.com/products-and-docs/apis/discovery-api/v2/#anchor_find

let apiKey = "************"
    
    struct EventResponse : Decodable{
        let events : [Event]
    }
    
    struct Event : Decodable{
        let id : String?
    }
    
    func fetchTMEvents() async throws -> [Event]{
        let urlTM = URL(string: "https://app.ticketmaster.com/discovery/v2/events.json?apikey=\(apiKey)")!
        let(data, _) = try await URLSession.shared.data(from: urlTM)
        let decoded = try JSONDecoder().decode(EventResponse.self, from: data)
        return decoded.events
    }
Task {
            do {
                let events = try await fetchTMEvents()
                print("API results \(events)")
            } catch {
                print("API error \(error)")
            }
        }

Full error:

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


Solution

  • Try these test models to fetch then decode the events. The example code in SwiftUI shows how to display the results.

    Note, you must have a valid apiKey otherwise the response will not be decodable.

    To get the full set of struct models, just copy the json data (all of it) to https://app.quicktype.io/ and the bulk of the code is generated for you. Adjust that code to suit your needs.

    You will have to consult the docs to determine which struct/properties are optional, then add ? to them.

    struct ContentView: View {
        @State var events: [Event] = []
        
        var body: some View {
            List(events) { event in
                Text(event.name)
            }
            .task {
                do {
                    if let results = try await fetchTMEvents() {
                        events = results
                    }
                } catch {
                    print("---> error: \(error)")
                }
            }
        }
        
        func fetchTMEvents() async throws -> [Event]? {
            let apiKey = "xxxxxxx"
            let urlTM = URL(string: "https://app.ticketmaster.com/discovery/v2/events.json?apikey=\(apiKey)")!
            let(data, _) = try await URLSession.shared.data(from: urlTM)
            // print(String(data: data, encoding: .utf8))
            let decoded = try JSONDecoder().decode(EventResponse.self, from: data)
            return decoded.embedded.events
        }
    }
    
    struct EventResponse: Codable {
        let embedded: ResponseEmbedded
        let page: Page
    
        enum CodingKeys: String, CodingKey {
            case page
            case embedded = "_embedded"
        }
    }
    
    struct ResponseEmbedded: Codable {
        let events: [Event]?
    }
    
    struct Event: Codable, Identifiable {
        let name, type, id, url, locale: String
    }
    
    struct Page: Codable {
        let size, totalElements, totalPages, number: Int
    }