I have these two JSON objects
[
{"name": "Popular Movies",
"description": "Basic movie description",
"type": "movies",
"items": [ { "id": 15, "name": "Sample movie", "movieSPT": ""}]
},
{"name": "Popular TV Shows",
"description": "Basic shows description",
"type": "tvshows",
"items": [ { "id": 15, "name": "Sample show", "showSPT": ""}]
}
]
Then i created two decodable structs, for shows and for movies:
struct Movie: Decodable {
let id: Int
let name: String
let movieSPT: String
}
struct TVShow: Decodable {
let id: Int
let name: String
let showSPT: String
}
So, when i create an object for main response, what is the best way to create an items array depends on type value? I know i can create both showSPT and movieSPT with optional properties for some unique struct, but is it the right way? Also, if these two models will have a lot of properties, the combine struct will be too big.
struct Blocks : Decodable {
let name: String
let description: String
let type: String
let items: [Movie] or [Show] based on type????
}
There are a couple of solutions. One of them is an enum with associated values
let jsonString = """
[{"name": "Popular Movies", "description": "Basic movie description", "type": "movies",
"items": [ { "id": 15, "name": "Sample movie", "movieSPT": ""}]
},
{"name": "Popular TV Shows", "description": "Basic shows description", "type": "tvshows",
"items": [ { "id": 15, "name": "Sample show", "showSPT": ""}]
}
]
"""
let data = Data(jsonString.utf8)
struct Movie : Decodable {
let id: Int
let name, movieSPT: String
}
struct TVShow : Decodable {
let id: Int
let name, showSPT: String
}
enum MediaType {
case movie([Movie]), tvShow([TVShow])
}
struct Media : Decodable {
let name : String
let description : String
let items : MediaType
private enum CodingKeys : String, CodingKey { case name, description, type, items }
init(from decoder : Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decode(String.self, forKey: .name)
self.description = try container.decode(String.self, forKey: .description)
let type = try container.decode(String.self, forKey: .type)
if type == "movies" {
let movieData = try container.decode([Movie].self, forKey: .items)
items = .movie(movieData)
} else { // add better error handling
let showData = try container.decode([TVShow].self, forKey: .items)
items = .tvShow(showData)
}
}
}
do {
let result = try JSONDecoder().decode([Media].self, from: data)
print(result)
} catch {
print(error)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With