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 Player
s 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
/games
and another one toplayers
and somehow merge them before decoding? - should I initialize my
Player
s 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