【问题标题】:Pulling data from TicketMasters API (Swift 4.0/Decodable)从 TicketMasters API 中提取数据(Swift 4.0/Decodable)
【发布时间】:2018-03-26 02:49:39
【问题描述】:

我目前正在学习 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))

我试图做的只是在调试区域打印出事件的名称,但什么都没有显示。我有一个遵循名为 Events 的可解码协议的结构:

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)),但是当我只想显示名称时,我得到了错误。

这是数据结构的图像以供参考。是因为嵌入的部分吗?任何帮助将不胜感激!

【问题讨论】:

    标签: arrays json swift api dictionary


    【解决方案1】:

    我使用 quicktype 为 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 }
    

    【讨论】:

    • 不错的答案!救生工具。
    • 您是否了解我们如何使用我们的 iOS 应用从 TicketMaster 购买机票。我有一个应用程序,我正在从我们的服务器获取 TicketMaster 活动(一个脚本获取数据并填充我们的数据库)但现在我需要在 iOS 应用程序中购买票
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    • 2018-07-08
    • 1970-01-01
    • 2011-10-19
    • 2013-06-14
    相关资源
    最近更新 更多