I'm trying to decode "dependent" JSON API responses in Swift. Let's imagine a fictional API with two endpoints:
/players, returns an array of objects with following attributes:id, an integer representing the player IDname, a string representing the player name
/games, returns an array of objects with following attributes:name, a string representing the name of the gameplayerId1, an integer representing the ID of the first playerplayerId2, an integer representing the ID of the second player
I model each type with a Swift struct:
struct Player: Decodable {
var id: Int
var name: String?
}
struct Game: Decodable {
var name: String
var player1: Player
var player2: Player
enum CodingKeys: String, CodingKey {
case name
case player1 = "playerId1"
case player2 = "playerId2"
}
}
I want to decode the response from /games into an array of Game objects, with correct Players attributes, so I extended Game with a custom initializer but I don't know how to retrieve all player attributes:
extension Game {
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
name = try values.decode(String.self, forKey: .name)
// HOW SHOULD I RETRIEVE THE PLAYER'S NAME GIVEN THEIR ID HERE?
// |
// |
// V
player1 = Player(id: try values.decode(Int.self, forKey: .player1), name: nil)
player2 = Player(id: try values.decode(Int.self, forKey: .player2), name: nil)
}
}
To summarize, the API response from /games does not contain all the information I need for full initialization, so how should I proceed:
- can/should I make two API calls, one to
/gamesand another one toplayersand somehow merge them before decoding? - should I initialize my
Players only partly (leaving unknown stuff tonil) and fill the details later? (That sound dangerous and cumbersome.) - anything else?
If you want to experiment with it, you can find a full example here