簡體   English   中英

從TicketMasters API提取數據(Swift 4.0 /可解碼)

[英]Pulling data from TicketMasters API (Swift 4.0/Decodable)

我正在學習有關API和Decodable的當前知識和實踐知識,我想嘗試使用其API在Ticketmaster上打印每個事件的名稱。 盡一切努力,我都將這個錯誤呈現給我:

Error serializing JSON: typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))

我試圖做的是僅打印調試區域中事件的名稱,但什么都沒有顯示。 我有一個遵循事件可解碼協議的結構:

struct Event: Decodable {
let name: String? }

我嘗試使用我的API密鑰從Ticketmaster請求信息:

//API String Request
    let jsonUrlString = "https://app.ticketmaster.com/discovery/v2/events.json?countryCode=US&apikey=zqqqmkCdkfslHeaCvqXbxQZFGNXHoAT2"
    guard let url = URL(string: jsonUrlString) else { return }

    //Method to pull information from Ticketmasters API
    URLSession.shared.dataTask(with: url) { (data, response, err) in
        guard let data = data else { return }
        let dataAsString = String(data: data, encoding: .utf8)
        print(dataAsString)

        do {
            let events = try JSONDecoder().decode([Event].self, from: data)
            print(events)
            print()
            print("Done.")
        } catch let jsonErr {
            print("Error serializing JSON:", jsonErr)
        }
    }.resume()

我究竟做錯了什么? 它正確地抓取數據,由於我有打印語句(print(dataAsString)),我可以告訴它,但是當我只想顯示名稱時,我得到了錯誤。

這是供參考的數據結構圖。 是因為嵌入了一部分嗎? 任何幫助將不勝感激!

在此處輸入圖片說明

我使用Codables為TicketMaster API響應生成了Codables

typealias TicketMaster = OtherTicketMaster

struct OtherTicketMaster: Codable {
    let links: OtherOtherLinks
    let embedded: Embedded
    let page: Page
}

struct OtherOtherLinks: Codable {
    let last: OtherAttraction
    let first: OtherAttraction
    let next: OtherAttraction
    let otherSelf: OtherAttraction
}

struct OtherAttraction: Codable {
    let href: String
}

struct Embedded: Codable {
    let events: [Event]
}

struct Event: Codable {
    let info: String?
    let classifications: [Classification]
    let links: OtherLinks
    let embedded: OtherEmbedded
    let accessibility: Accessibility?
    let id: String
    let dates: Dates
    let images: [Image]
    let priceRanges: [PriceRange]
    let sales: Sales
    let name: String
    let locale: String
    let pleaseNote: String?
    let promoter: Promoter
    let products: [Products]?
    let promoters: [Promoter]
    let test: Bool
    let seatmap: Seatmap
    let type: String
    let url: String
}

struct Classification: Codable {
    let primary: Bool
    let subGenre: Genre
    let genre: Genre
    let segment: Genre
    let subType: Genre
    let type: Genre
}

struct Genre: Codable {
    let id: String
    let name: String
}

struct OtherLinks: Codable {
    let otherSelf: OtherAttraction
    let attractions: [OtherAttraction]
    let venues: [OtherAttraction]
}

struct OtherEmbedded: Codable {
    let attractions: [Attraction]
    let venues: [Venue]
}

struct Attraction: Codable {
    let images: [Image]
    let classifications: [Classification]
    let links: Links
    let id: String
    let name: String
    let type: String
    let locale: String
    let test: Bool
    let upcomingEvents: UpcomingEvents
    let url: String
}

struct Links: Codable {
    let otherSelf: OtherAttraction
}

struct UpcomingEvents: Codable {
    let ticketmaster: Int?
    let total: Int
    let tmr: Int?
}

struct Venue: Codable {
    let generalInfo: GeneralInfo?
    let postalCode: String
    let boxOfficeInfo: BoxOfficeInfo?
    let accessibleSeatingDetail: String?
    let links: Links
    let address: Address
    let country: Country
    let city: City
    let dmas: [Dma]
    let location: Location
    let images: [Image]?
    let id: String
    let locale: String
    let name: String
    let markets: [Market]
    let parkingDetail: String
    let timezone: String
    let state: State
    let social: Social?
    let test: Bool
    let upcomingEvents: UpcomingEvents
    let type: String
    let url: String
}

struct GeneralInfo: Codable {
    let childRule: String?
    let generalRule: String
}

struct BoxOfficeInfo: Codable {
    let openHoursDetail: String
    let acceptedPaymentDetail: String
    let phoneNumberDetail: String?
    let willCallDetail: String
}

struct Address: Codable {
    let line1: String
}

struct Country: Codable {
    let countryCode: String
    let name: String
}

struct City: Codable {
    let name: String
}

struct Dma: Codable {
    let id: Int
}

struct Location: Codable {
    let latitude: String
    let longitude: String
}

struct Market: Codable {
    let id: String
}

struct State: Codable {
    let name: String
    let stateCode: String
}

struct Social: Codable {
    let twitter: Twitter
}

struct Twitter: Codable {
    let handle: String
}

struct Accessibility: Codable {
    let info: String
}

struct Dates: Codable {
    let start: Start
    let spanMultipleDays: Bool
    let status: Status
    let timezone: String
}

struct Start: Codable {
    let localDate: String
    let dateTBD: Bool
    let dateTBA: Bool
    let dateTime: String
    let noSpecificTime: Bool
    let localTime: String
    let timeTBA: Bool
}

struct Status: Codable {
    let code: String
}

struct Image: Codable {
    let fallback: Bool
    let ratio: String?
    let attribution: String?
    let height: Int
    let url: String
    let width: Int
}

struct PriceRange: Codable {
    let max: Double
    let currency: String
    let min: Double
    let type: String
}

struct Sales: Codable {
    let presales: [Presales]?
    let otherPublic: Public
}

struct Presales: Codable {
    let endDateTime: String
    let startDateTime: String
    let description: String?
    let name: String
    let url: String?
}

struct Public: Codable {
    let startDateTime: String
    let endDateTime: String
    let startTBD: Bool
}

struct Promoter: Codable {
    let id: String
    let description: String
    let name: String
}

struct Products: Codable {
    let name: String
    let id: String
    let type: String
    let url: String
}

struct Seatmap: Codable {
    let staticUrl: String
}

struct Page: Codable {
    let size: Int
    let number: Int
    let totalElements: Int
    let totalPages: Int
}

// Serialization extensions

extension OtherTicketMaster {
    static func from(json: String, using encoding: String.Encoding = .utf8) -> OtherTicketMaster? {
        guard let data = json.data(using: encoding) else { return nil }
        return OtherTicketMaster.from(data: data)
    }

    static func from(data: Data) -> OtherTicketMaster? {
        let decoder = JSONDecoder()
        return try? decoder.decode(OtherTicketMaster.self, from: data)
    }

    var jsonData: Data? {
        let encoder = JSONEncoder()
        return try? encoder.encode(self)
    }

    var jsonString: String? {
        guard let data = self.jsonData else { return nil }
        return String(data: data, encoding: .utf8)
    }
}

extension Accessibility {
    enum CodingKeys: String, CodingKey {
        case info
    }
}

extension Address {
    enum CodingKeys: String, CodingKey {
        case line1
    }
}

extension Attraction {
    enum CodingKeys: String, CodingKey {
        case images
        case classifications
        case links = "_links"
        case id
        case name
        case type
        case locale
        case test
        case upcomingEvents
        case url
    }
}

extension BoxOfficeInfo {
    enum CodingKeys: String, CodingKey {
        case openHoursDetail
        case acceptedPaymentDetail
        case phoneNumberDetail
        case willCallDetail
    }
}

extension City {
    enum CodingKeys: String, CodingKey {
        case name
    }
}

extension Classification {
    enum CodingKeys: String, CodingKey {
        case primary
        case subGenre
        case genre
        case segment
        case subType
        case type
    }
}

extension Country {
    enum CodingKeys: String, CodingKey {
        case countryCode
        case name
    }
}

extension Dates {
    enum CodingKeys: String, CodingKey {
        case start
        case spanMultipleDays
        case status
        case timezone
    }
}

extension Dma {
    enum CodingKeys: String, CodingKey {
        case id
    }
}

extension Embedded {
    enum CodingKeys: String, CodingKey {
        case events
    }
}

extension Event {
    enum CodingKeys: String, CodingKey {
        case info
        case classifications
        case links = "_links"
        case embedded = "_embedded"
        case accessibility
        case id
        case dates
        case images
        case priceRanges
        case sales
        case name
        case locale
        case pleaseNote
        case promoter
        case products
        case promoters
        case test
        case seatmap
        case type
        case url
    }
}

extension GeneralInfo {
    enum CodingKeys: String, CodingKey {
        case childRule
        case generalRule
    }
}

extension Genre {
    enum CodingKeys: String, CodingKey {
        case id
        case name
    }
}

extension Image {
    enum CodingKeys: String, CodingKey {
        case fallback
        case ratio
        case attribution
        case height
        case url
        case width
    }
}

extension Links {
    enum CodingKeys: String, CodingKey {
        case otherSelf = "self"
    }
}

extension Location {
    enum CodingKeys: String, CodingKey {
        case latitude
        case longitude
    }
}

extension Market {
    enum CodingKeys: String, CodingKey {
        case id
    }
}

extension OtherAttraction {
    enum CodingKeys: String, CodingKey {
        case href
    }
}

extension OtherEmbedded {
    enum CodingKeys: String, CodingKey {
        case attractions
        case venues
    }
}

extension OtherLinks {
    enum CodingKeys: String, CodingKey {
        case otherSelf = "self"
        case attractions
        case venues
    }
}

extension OtherOtherLinks {
    enum CodingKeys: String, CodingKey {
        case last
        case first
        case next
        case otherSelf = "self"
    }
}

extension OtherTicketMaster {
    enum CodingKeys: String, CodingKey {
        case links = "_links"
        case embedded = "_embedded"
        case page
    }
}

extension Page {
    enum CodingKeys: String, CodingKey {
        case size
        case number
        case totalElements
        case totalPages
    }
}

extension Presales {
    enum CodingKeys: String, CodingKey {
        case endDateTime
        case startDateTime
        case description
        case name
        case url
    }
}

extension PriceRange {
    enum CodingKeys: String, CodingKey {
        case max
        case currency
        case min
        case type
    }
}

extension Products {
    enum CodingKeys: String, CodingKey {
        case name
        case id
        case type
        case url
    }
}

extension Promoter {
    enum CodingKeys: String, CodingKey {
        case id
        case description
        case name
    }
}

extension Public {
    enum CodingKeys: String, CodingKey {
        case startDateTime
        case endDateTime
        case startTBD
    }
}

extension Sales {
    enum CodingKeys: String, CodingKey {
        case presales
        case otherPublic = "public"
    }
}

extension Seatmap {
    enum CodingKeys: String, CodingKey {
        case staticUrl
    }
}

extension Social {
    enum CodingKeys: String, CodingKey {
        case twitter
    }
}

extension Start {
    enum CodingKeys: String, CodingKey {
        case localDate
        case dateTBD
        case dateTBA
        case dateTime
        case noSpecificTime
        case localTime
        case timeTBA
    }
}

extension State {
    enum CodingKeys: String, CodingKey {
        case name
        case stateCode
    }
}

extension Status {
    enum CodingKeys: String, CodingKey {
        case code
    }
}

extension Twitter {
    enum CodingKeys: String, CodingKey {
        case handle
    }
}

extension UpcomingEvents {
    enum CodingKeys: String, CodingKey {
        case ticketmaster
        case total = "_total"
        case tmr
    }
}

extension Venue {
    enum CodingKeys: String, CodingKey {
        case generalInfo
        case postalCode
        case boxOfficeInfo
        case accessibleSeatingDetail
        case links = "_links"
        case address
        case country
        case city
        case dmas
        case location
        case images
        case id
        case locale
        case name
        case markets
        case parkingDetail
        case timezone
        case state
        case social
        case test
        case upcomingEvents
        case type
        case url
    }
}

// Helpers

class JSONNull: Codable {
    public init() {
    }

    public required init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if !container.decodeNil() {
            throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
        }
    }

    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encodeNil()
    }
}

您將看到JSON響應的頂級類型不是[Event] ,而是TicketMaster類型的對象,該對象的[Event]值嵌套在.embedded.events 這是獲取所有事件名稱的方法:

let ticketMaster = TicketMaster.from(json: dataAsString)!
let eventNames = ticketMaster.embedded.events.map { $0.name }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM