我正在学习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语句(print(dataAsString)),但是当我只想显示名称时,我得到了错误。
这里是数据结构的图像供参考。是因为嵌入式部分?真的很感激任何帮助!
答案 0 :(得分:3)
我使用quicktype生成Codables
TicketMaster API响应:
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]
值嵌套在{ {1}}。以下是如何获取所有事件的名称:
.embedded.events