Errors on app and simulator not starting, Xcode 12.2

Hi all. My previous issue got fixed, but I have a new issue and a question. My error is saying,

Fatal error: Couldn't parse Rest.json as Array<Restaurant>:
dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Garbage at end." UserInfo={NSDebugDescription=Garbage at end.}))): file SaiMirrasKitchen/ModelData.swift, line 30

and my question is, what do I put to fix the simulator in my RestaurantRow.swift file(line 21)?

Thanks,
Harri

Github Repository

Your JSON is not valid. You need braces { } at the beginning and end.

As for what to put in your preview, you need a Restaurants object.

@roosterboy
It says that the type restaurant has no value of ‘subscript’

What did you put in there?

@roosterboy

I put:

  RestaurantRows(restaurant: Restaurants[0])

Yeah, that’s not what you need. Restaurants is a type; you need an instance of that type. Something like this:

struct RestaurantRows_Previews: PreviewProvider {
    static var previews: some View {
        let restaurants = Restaurants(restaurants: [
                Rest(id: 1001, name: "Chapathi", category: "Tiffin", description: "...", imageName: "Chapathi")
            ]
        )
        RestaurantRows(restaurant: restaurants)
    }
}

But this is just an instance, right? Or should I put … for all the strings.
And also, why is the error coming up? Do I need to fix anything in my code?

It’s just for the preview, so put as many as you want/need to see so you can get a good idea what it will look like with real data. If it will be populating a list, then maybe 2-3 Rest objects.

The error is because the type Restaurants is not an array or dictionary or set or any other kind of collection that can be indexed by a subscript. But you were trying to access a subscript on it: Restaurants[0]

Also, I would advise working on the naming of your structs and properties. It’s kind of confusing as it is now. For instance:

RestaurantRows implies a listing of restaurants, but the property to store those items is called restaurant, singular. But its type is Restaurants, plural. Very confusing.

Then, your Rest struct. What is a Rest? And does your JSON even really describe restaurants? All the descriptions seem like various types of food that would be served at a restaurant.

Choosing good names to use in your code is very often the first and best way to figure out what is going on and can even help you find bugs in your logic.

@roosterboy
I meant my garbage at end error…

I explained that one already:

@Dangerous_Duos

What rooster boy is getting at is that this is what your json file should look like with the opening brace right at the top and the closing brace right at the bottom.

Use this link to validate json. It’s a sure way of you finding out if anything is screwed up.

{
"restaurants": [
    {
        "id":1001,
        "name":"Chapathi",
        "imageName":"Chapathi",
        "description":"Chapathi is a type of roti bread that is served all around the world.It is made of of wheat flour, oil, and water. Rolled and placed on a tawa.",
       "category":"Tiffin"
    },
    {
        "id":1002,
        "name":"Methi Paratha",
        "imageName":"Methi-Paratha-3",
        "description":"Methi Paratha is a healthy type of flaky bread that is made of fenugreek and spices. It is very healthy, and is served with Masala Curd and Lettuce.",
        "category":"Tiffin"
    },
    {
        "id":1003,
        "name":"Aloo Paratha",
        "imageName":"AlooParatha",
        "description":"Aloo Paratha is a stuffed paratha made with cumin and potatoes. It is very healthy in nutrients, and is served with Masala Curd and Lettuce.",
        "category":"Tiffin"
    },
    {
        "id":1004,
        "name":"Idli",
        "imageName":"Idli",
        "description":"Idli is one of the worlds healthiest foods to eat. It is a steamed lentil cake, with softness and fluffiness than a pillow. It is served with coconut chutney.",
        "category":"Tiffin"
    },
    {
        "id":1005,
        "name":"Paniyaram",
        "imageName":"Paniyaram",
        "description":"A snack to a dinner, Paniyaram is great for everyone. It is made out of lentils, and crispy on the outside with fluffiness on the inside. Served with coconut chutney.",
        "category":"Tiffin"
    },
    {
        "id":1006,
        "name":"Pongal",
        "imageName":"Pongal",
        "description":"Pongal is a great way to start your day. The presence of ghee and curry leaves make it so scrumptious. Great taste with cashews as well. Served with coconut chutney.",
        "category":"Tiffin"
    },
    {
     "id":1007,
     "name":"Vegetable Rava Kichidi",
     "imageName":"Kichidi",
     "description":"A rava deliciousness. Filled with carrots, beans, and many more. Just a hint of ghee will make your day. Served with coconut chutney.",
     "category":"Tiffin"
    },
    {
     "id":1008,
     "name":"Methi Corn Pulav",
     "imageName":"Methi Pulav",
     "description":"A veg masala rice. Made with corn and methi. With the aroma of basmati rice and fresh masala. Served with onions and raita.",
     "category":"Rice"
    },
    {
     "id":1009,
     "name":"Vegetable Biryani",
     "imageName":"VegBiriyani",
     "description":"A savory lunch, filled with steamed carrots, beans, and cauliflower. With the aroma of a traditional seeraga samba rice, this biriyani boasts due to it's in-house masala. This is served with raita and kurma.",
     "category":"Rice"
    },
    {
     "id":1010,
     "name":"Chicken Biryani",
     "imageName":"chkbiriyani",
     "description":"This yummy biriyani is made up of organic chicken, amd filled with the most aromatic biryani rice ever, seeraga samba. With our in house masala, this day just gets better and is served with raita and kurma.",
     "category":"Rice"
    },
    {
     "id":1011,
     "name":"Chilli Paneer",
     "imageName":"chilpaneer",
     "description":"Cottage cheese marinated in curd and fried, with sautted vegetables, this makes the perfect starter for vegetarians and non - vegetarians. Served with mint chutney and avocado dip.",
     "category":"Appetizers"
    },
    {
     "id":1012,
     "name":"Cauliflower 65",
     "imageName":"gobi65",
     "description":"Cauliflower steamed and cooled, and then dipped in batter as fried in peanut oil. This crispy starter will leave the plate finished, and is served with mint chutney and avocado dip.",
     "category":"Appetizers"
    },
    {
     "id":1013,
     "name":"Red Chicken Fry",
     "imageName":"redchk",
     "description":"Chicken cut into bite sized pieces and then marinated in spices and curd. Then pan seared to make it taste and feel elegant. Served with mint chutney and avocado dip.",
     "category":"Appetizers"
    },
    {
     "id":1014,
     "name":"Egg Kurma",
     "imageName":"eggkurma",
     "description":"Slit eggs boiled and mixed with gravy. Made up of spices and coconut. Great for both rice and chapathi.",
     "category":"Curries"
    },
    {
     "id":1015,
     "name":"Chicken Kheema",
     "imageName":"chkkhema",
     "description":"Chicken minced and made into a curry with great flavored curry leaves. Eat with anything of your choice.",
     "category":"Curries"
    },
    {
     "id":1016,
     "name":"Sambar",
     "imageName":"sambar",
     "description":"A great South Indian way to start your day. Dal boiled with drumsticks and onions. A great taste with many dishes.",
     "category":"Curries"
    },
    {
     "id":1017,
     "name":"Paneer Butter Masala",
     "imageName":"paneermasala",
     "description":"Cottage cheese gravy with methi and all creamy deliciousness. The best gravy to eat with any flaky bread.",
     "category":"Curries"
    }
]
}

Harri,

For what it is worth, I wrote some code to decode your json file and present the results in a List view and that works when the json is formatted correctly.

@roosterboy
@Chris_Parker

Thank you so much for this help! I have been trying to find what to debug for almost a week! The simulator now works without any error! I will post the screenshot of the app once I am done!

Greatly Appreciated,
Harri

Also, I have a question. What value do I put in the RestaurantRows.swift file, in the body variable, to load the items from my JSON file? Because when I put:

struct RestaurantRows: View {
    
    var restaurant:Restaurants
    
    var body: some View {
        Image(Rest.imageName)
}

struct RestaurantRows_Previews: PreviewProvider {
    static var previews: some View {
        let restaurants = Restaurants(restaurants: [
                Rest(id: 1001, name: "...", category: "...", description: "...", imageName: "...")
            ]
        )
        RestaurantRows(restaurant: restaurants)
    }
}
}

Because when I put Rest.imageName, it says that
"type ‘Restaurants’ has no member ‘imageName’


SchemeBuildError: Failed to build the scheme “SaiMirrasKitchen”

type ‘Restaurants’ has no member ‘imageName’

Build target SaiMirrasKitchen:
warning: Capabilities for Signing & Capabilities may not function correctly because its entitlements use a placeholder team ID. To resolve this, select a development team in the SaiMirrasKitchen editor. (in target ‘SaiMirrasKitchen’ from project ‘SaiMirrasKitchen’)

Compile RestaurantRows.swift (x86_64):
/Users/sathishdamodaran/Desktop/SaiMirrasKitchen/SaiMirrasKitchen/RestaurantRows.swift:15:27: error: type ‘Restaurants’ has no member ‘imageName’
Image(Restaurants.imageName)
~~~~~~~~~~~ ^~~~~~~~~"

The restaurant property is of type Restaurants. Let’s take a look at the type definition for Restaurants:

struct Restaurants: Decodable {
    let restaurants: [Rest]
}

No property called imageName. Instead, Restaurants has a single property restaurants, which is an array of Rest structs. And the Rest type does have an imageName property:

struct Rest: Hashable, Codable, Identifiable{
    var id: Int
    var name: String
    var category: String
    var description: String
    var imageName: String

    enum Category: String, CaseIterable{
        case Tiffin = "Tiffin"
        case Rice = "Rice"
        case Appetizers = "Appetizers"
        case Curries = "Curries"
    }

}

So what you need here is an instance of a Rest, which you can get by subscripting the restaurant property of your View:

Image(restaurant[0].imageName)

I would suggest reading up on the difference between types and instances of a type. You’ve made this same kind of error before.

@roosterboy
Thank You, but if I paste the code the way it is, it says that the value of restaurants has no subscripts…

Oops, sorry, that should be:

Image(restaurant.restaurants[0].imageName)

I got confused because of the naming of your properties and types.

Harri, Can I make a suggestion with regard to how you have named your struct?

Consider the following:

struct Restaurant: Decodable {
    let menuItems: [MenuItem]
}

struct MenuItem: Hashable, Decodable, Identifiable {
    var id: Int
    var name: String
    var category: String
    var description: String
    var imageName: String

    enum Category: String, CaseIterable{
        case Tiffin = "Tiffin"
        case Rice = "Rice"
        case Appetizers = "Appetizers"
        case Curries = "Curries"
    }

}

Rather than your JSON file have the ‘array’ of “restaurants”, change the name to “menuItems”.

To me that more accurately reflects the data you are dealing with. Your high level struct can still remain named Restaurant and a restaurant has a list of menuItems. Does that make sense?

@roosterboy
@Chris_Parker

I now have another error in another file. So my RestaurantList.swift went fine, but I am creating another file called RestaurantRows.swift, and I am getting a similar error.

Fatal error: Couldn't parse Rest.json as Array<Restaurants>:
typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil)): file SaiMirrasKitchen/ModelData.swift, line 28

Can someone please tell me what to do? I am sorry for the inconvenience.

  • Harri

Please show the code that is causing that error.

But just from the error itself, it seems like you aren’t using the correct data structures when decoding your JSON. It’s looking for an array of items but you are supplying it with an object with a key/value structure.

So, it wants something like this:

[
    {
        "key": "value"
    }
]

but you are giving it something like this:

{
    "key": "value"
}

But without seeing your code, it’s hard to say exactly what the hitch is.