I am trying to create a request object that allows me to use multiple different dynamic objects based on an API call. I currently have the following.
let json = """
{
"object": "bottle",
"has_more": false,
"data": [
{
"id": "5ffa81e7-1d91-43b5-83cc-9ee1ab634c7b",
"name": "14 Hands Hot to Trot White Blend",
"price": "$8.99",
"image": "https://cdn11.bigcommerce.com/s-7a906/images/stencil/1000x1000/products/8186/10996/14-Hands-Hot-to-Trot-White-Blend__56901.1488985626.jpg?c=2",
"sku": "088586004490",
"size": "750ML",
"origination": "USA, Washington",
"varietal": "White Wine",
"information": "14 Hands Hot to Trot White Blend",
"proof": 121.5,
"brand_id": "1",
"rating": 1,
"review_count": 5
}
]
}
"""
enum RequestData {
case bottle([Bottle])
}
enum ObjectType: String, Decodable {
case bottle
}
struct Request: Decodable {
let object: ObjectType
let hasMore: Bool
let data: RequestData
enum CodingKeys: String, CodingKey { case hasMore = "has_more", object, data}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.object = try container.decode(ObjectType.self, forKey: .object)
self.hasMore = try container.decode(Bool.self, forKey: .hasMore)
switch object {
case .bottle:
let bottleData = try container.decode([Bottle].self, forKey: .data)
data = RequestData.bottle(bottleData)
}
}
}
struct Bottle: Decodable {
let id: String
let name: String
let price: String
let image: String
let sku: String
let size: String
let origination: String
let varietal: String
let information: String
let proof: Float
let brand_id: String
let rating: Int
let review_count: Int
}
let decoder = JSONDecoder()
let requestData = try decoder.decode(Request.self, from: Data(json .utf8))
print(requestData)
It is working as expected, however, I am just not entirely sure how I can access the struct attributes. If I run the above, I get the following output.
Request(object: __lldb_expr_217.ObjectType.bottle, hasMore: false, data: __lldb_expr_217.RequestData.bottle([__lldb_expr_217.Bottle(id: "5ffa81e7-1d91-43b5-83cc-9ee1ab634c7b", name: "14 Hands Hot to Trot White Blend", price: "$8.99", image: "https://cdn11.bigcommerce.com/s-7a906/images/stencil/1000x1000/products/8186/10996/14-Hands-Hot-to-Trot-White-Blend__56901.1488985626.jpg?c=2", sku: "088586004490", size: "750ML", origination: "USA, Washington", varietal: "White Wine", information: "14 Hands Hot to Trot White Blend", proof: 121.5, brand_id: "1", rating: 1, review_count: 5)]))
My goal here is to loop over this Request
object and take the name from each Bottle id within that Request
object. How can I achieve this? It seems simple I just can't get it to work.
CodePudding user response:
Lets say you add a new bottle to the list to have two bottle in result
{
"id":"5ffa81e7-1d91-43b5-83cc-9ee1ab634c8b",
"name":"New Bottle",
"price":"$7.99",
"image":"https://cdn11.bigcommerce.com/s-7a906/images/stencil/1000x1000/products/8186/10996/14-Hands-Hot-to-Trot-White-Blend__56901.1488985626.jpg?c=2",
"sku":"088586004491",
"size":"750ML",
"origination":"USA, Washington",
"varietal":"White Wine",
"information":"14 Hands Hot to Trot White Blend",
"proof":121.5,
"brand_id":"1",
"rating":1,
"review_count":5
}
you can switch over which enum is the result by doing
switch requestData.data {
case .bottle(let bottleList):
for bottle in bottleList {
print(bottle)
}
}
This will give output:
Bottle(id: "5ffa81e7-1d91-43b5-83cc-9ee1ab634c7b", name: "14 Hands Hot to Trot White Blend", price: "$8.99", image: "https://cdn11.bigcommerce.com/s-7a906/images/stencil/1000x1000/products/8186/10996/14-Hands-Hot-to-Trot-White-Blend__56901.1488985626.jpg?c=2", sku: "088586004490", size: "750ML", origination: "USA, Washington", varietal: "White Wine", information: "14 Hands Hot to Trot White Blend", proof: 121.5, brand_id: "1", rating: 1, review_count: 5)
Bottle(id: "5ffa81e7-1d91-43b5-83cc-9ee1ab634c8b", name: "New Bottle", price: "$7.99", image: "https://cdn11.bigcommerce.com/s-7a906/images/stencil/1000x1000/products/8186/10996/14-Hands-Hot-to-Trot-White-Blend__56901.1488985626.jpg?c=2", sku: "088586004491", size: "750ML", origination: "USA, Washington", varietal: "White Wine", information: "14 Hands Hot to Trot White Blend", proof: 121.5, brand_id: "1", rating: 1, review_count: 5)
What happen if we decide to add more type?
Lets say you add Pillow
to object type
struct Pillow: Decodable {
let id: String
}
enum RequestData {
case bottle([Bottle])
case pillow([Pillow])
}
enum ObjectType: String, Decodable {
case bottle, pillow
}
Now you can just add more case to the print
switch requestData.data {
case .bottle(let bottleList):
for bottle in bottleList {
print(bottle)
}
case .pillow(let pillowList):
for pillow in pillowList {
print(pillow)
}
}