Home > Mobile >  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?

Time:12-06

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?

CodePudding user response:

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.

CodePudding user response:

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")

CodePudding user response:

In the JSON data you provided, the cars field is an array of objects, not a dictionary. In other words, each element of the array is a separate car object with its own properties, such as name and price.

In the Cars and Car structs that you defined, the cars property of the Cars struct is declared as an array of Car objects. This matches the structure of the JSON data, so when you decode the JSON using the JSONDecoder class, the decoder will create a new Cars object with an array of Car objects as its cars property.

In the last line of your code, you are accessing the cars property of the Cars object that was created by the JSONDecoder, and assigning it to a new variable called listOfCars. This is why you are using the dot syntax (i.e. result.cars) to access the property, rather than using square bracket syntax (i.e. result["cars"]).

  • Related