I expect the result to be a dictionary but it is accessed like a property… why?

I expect the result to be a dictionary but it is accessed like a property… why?

Problem Description:

I have this JSON coming from a server…

{
  "cars": [
    {
      "name": "Ferrari",
      "price": "100"
    },
    {
      "name": "Lamborghini",
      "price": "200"
    },
    {
      "name": "Ford Pinto",
      "price": "1"
    }
  ]
}

This JSON is a dictionary called cars that contains an array of cars, right?

Then I have this struct…

struct Cars: Codable {
    let cars: [Car]
}


struct Car: Codable, Hashable, Identifiable {
    let id = UUID()
    let name: String
    let price: String
}

and I decode the JSON using this:

let (data, _) = try await urlSession.data(from: url)
let result = try JSONDecoder().decode(Cars.self, from: data)
let listOfCars = result.cars

This is something I don’t understand.

in result.cars, cars is a property of result that was declared as an array in the struct Cars. Not a dictionary.

I was expecting to access it using result["cars"].

Why is that?

Solution – 1

In your code here…

let (data, _) = try await urlSession.data(from: url)
let result = try JSONDecoder().decode(Cars.self, from: data)
let listOfCars = result.cars

result is an instance of the Struct Cars. Your set up code has told Swift how to translate from a JSON dictionary into your own Struct.

So everything inside of result is accessed just like how you would access it in the following…

let result = Cars(cars: [
  Car(name: "Ford", price: "£10,000")
])

print(result.cars)

The only difference is how you are creating it. Instead of using the init method like this you are using a JSON decode to decode some JSON into your custom type.

Solution – 2

As said in the comments and answers, it takes a result type according to your decode strategy. In your code result type is Cars not a dictionary. So you access the properties with using result.cars

If you want something as dictionary instead, you need to decode it like

let result = try decode.decode([String : [Car]].self, from: data)

Now you can access them like a dictionar

print(result["cars"]?.first?.name) // Optional("Ferrari")
Rate this post
We use cookies in order to give you the best possible experience on our website. By continuing to use this site, you agree to our use of cookies.
Accept
Reject