Last active
February 6, 2023 12:31
-
-
Save cliss/c4c788b6cee2a8f3d307b965c33cdc4c to your computer and use it in GitHub Desktop.
Revisions
-
cliss revised this gist
Feb 2, 2023 . 1 changed file with 0 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,7 +2,6 @@ import Foundation let json = """ { -
cliss created this gist
Feb 2, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,146 @@ // This is intended to be dropped in a Playground. import Foundation var greeting = "Hello, playground" let json = """ { "name": "Casey's Corner", "menu": [ { "itemType": "drink", "drinkName": "Dry Vodka Martini" }, { "itemType": "drink", "drinkName": "Jack-and-Diet" }, { "itemType": "appetizer", "appName": "Nachos" }, { "itemType": "entree", "entreeName": "Steak", "temperature": "Medium Rare" }, { "itemType": "entree", "entreeName": "Caesar Salad" }, { "itemType": "entree", "entreeName": "Grilled Salmon" } ] } """ struct Drink: Decodable { let drinkName: String } struct Appetizer: Decodable { let appName: String } struct Entree: Decodable { let entreeName: String let temperature: String? } struct Restaurant: Decodable { let name: String let menu: [Any] // The normal, expected CodingKey definition for this type enum RestaurantKeys: CodingKey { case name case menu } // The key we use to decode each menu item's type enum MenuItemTypeKey: CodingKey { case itemType } // The enumeration that actually matches menu item types; // note this is **not** a CodingKey enum MenuItemType: String, Decodable { case drink case appetizer case entree } init(from decoder: Decoder) throws { // Get the decoder for the top-level object let container = try decoder.container(keyedBy: RestaurantKeys.self) // Decode the easy stuff: the restaurant's name self.name = try container.decode(String.self, forKey: .name) // Create a place to store our menu var inProgressMenu: [Any] = [] // Get a copy of the array for the purposes of reading the type var arrayForType = try container.nestedUnkeyedContainer(forKey: .menu) // Make a copy of this for reading the actual menu items. var array = arrayForType // Start reading the menu array while !arrayForType.isAtEnd { // Get the object that represents this menu item let menuItem = try arrayForType.nestedContainer(keyedBy: MenuItemTypeKey.self) // Get the type from this menu item let type = try menuItem.decode(MenuItemType.self, forKey: .itemType) // Based on the type, create the appropriate menu item // Note we're switching to using `array` rather than `arrayForType` // because we need our place in the JSON to be back before we started // reading this menu item. switch type { case .drink: let drink = try array.decode(Drink.self) inProgressMenu.append(drink) case .appetizer: let appetizer = try array.decode(Appetizer.self) inProgressMenu.append(appetizer) case .entree: let entree = try array.decode(Entree.self) inProgressMenu.append(entree) } } // Set our menu self.menu = inProgressMenu } } let data = json.data(using: .utf8)! let restaurant = try! JSONDecoder().decode(Restaurant.self, from: data) print("\(restaurant.name)") for item in restaurant.menu { if let d = item as? Drink { print(" +-- Drink: \(d.drinkName)") } else if let a = item as? Appetizer { print(" +-- Appetizer: \(a.appName)") } else if let e = item as? Entree { print(" +-- Entree: \(e.entreeName)") if let temp = e.temperature { print(" Temperature: \(temp)") } } } /* Expected output: * Casey's Corner * +-- Drink: Dry Vodka Martini * +-- Drink: Jack-and-Diet * +-- Appetizer: Nachos * +-- Entree: Steak * Temperature: Medium Rare * +-- Entree: Caesar Salad * +-- Entree: Grilled Salmon */