0

I'm making a small app to practice parsing JSON into a tableview, and I'm using the Ticketmaster API. This is the JSON, and these are the structs that I have set up:

struct Welcome: Decodable {
    let embedded: WelcomeEmbedded
    enum CodingKeys: String, CodingKey{
        case embedded = "_embedded"
    }
}

struct WelcomeEmbedded: Decodable {
    let events: [Event]
}

struct Event: Decodable {
    let name: String
    let dates: Dates
    let eventUrl: String?
    let embedded: EventEmbedded

    enum CodingKeys: String, CodingKey {
        case name
        case dates
        case eventUrl
        case embedded = "_embedded"
    }
}

struct EventEmbedded: Decodable {
    let venue: Venue
}

struct Dates: Decodable {
    let start, end: End
}

struct Venue: Decodable {
    let name: String
}

Before adding in the value let embedded: EventEmbedded to the Event struct, things worked fine, but after adding in that line, when running the app I get an error:

Error decoding JSON: typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "_embedded", intValue: nil), CodingKeys(stringValue: "events", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "_embedded", intValue: nil), CodingKeys(stringValue: "venue", intValue: nil)], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil))

I'm wondering how adding that line alone results in an error, is it anything to do with the fact that I have a value named embedded in two structs (Welcome and Event), and both use the coding key _embedded?

For some added detail, to parse the JSON I have a variable var eventData = [Event]() and call this function in viewDidLoad to populate eventData with the necessary data:

    fetchData(url: apiUrl) { (result: FetchResult<Welcome>) -> (Void) in

        switch result {
        case .success(let object): self.eventData = object.embedded.events
        case .failure(let error): print("\nError decoding JSON: \(error)\n\n")
        }
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    }

The error also says CodingKeys(stringValue: "venue", intValue: nil)], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.. But looking at the JSON, the data under venue is structured the same way as the rest of the values, and they don't give me an error.

What can I do differently here to get back on track?

6
  • The typeMismatch error is pretty clear: The value for key venue is an array (note the [] in the JSON): let venue: [Venue] Commented Jan 27, 2019 at 18:28
  • Oh man, I was really focusing on the wrong thing here. Sorry for the silly question! So I'm just going to change Venue to [Venue] then access the name value with a subscript then I think, correct? Commented Jan 27, 2019 at 18:33
  • Yes, cell.venueLabel.text = event.embedded.venue[0].name worked. You're amazing vadian thanks for pointing that out! Commented Jan 27, 2019 at 18:35
  • I'm curious though, why is it necessary to use the subscript to access the values in venue, but not events? They're both arrays, aren't they? Commented Jan 27, 2019 at 18:37
  • event is obviously one item of the array. Commented Jan 27, 2019 at 18:38

1 Answer 1

2

Please learn to read Codable errors. They are very, very, very descriptive.

Error decoding JSON: typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "_embedded", intValue: nil), CodingKeys(stringValue: "events", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "_embedded", intValue: nil), CodingKeys(stringValue: "venue", intValue: nil)], debugDescription: "Expected to decode Dictionary but found an array instead.", underlyingError: nil))

  • typeMismatch is the error type
  • CodingKeys(stringValue: "_embedded", CodingKeys(stringValue: "events"), CodingKeys(stringValue: "_embedded"), CodingKeys(stringValue: "venue") is the key path (_embedded/events/_embedded/venue)
  • Expected to decode Dictionary<String, Any> but found an array instead is the error message.

    • Expected is the wrong type you proposed.
    • found is the actual type.

      A dictionary is the struct, an array is an array of the struct.

Change EventEmbedded to

struct EventEmbedded: Decodable {
    let venue: [Venue]
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, it's a little more clear now that you point it out - I saw the error mention _embedded a few times and thought that there were issues there, when in fact the error message was just following the "path" through the values to the actual error of Expected to decode Dictionary but found an array instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.