Context
This is a follow-up question to that question I asked a few days ago, reading it beforehand is not strictly necessary though.
I have an API endpoint /common
, returning JSON data in that form:
{
"data":
{
"players": [
{
"id": 1,
"name": "John Doe"
},
{
"id": 15,
"name": "Jessica Thump"
}],
"games": [
{
"name": "Tic Tac Toe",
"playerId1": 15,
"playerId2": 1
}]
}
}
In further code snippets, it is assumed that this response is stored as a String
in the variable rawApiResponse
.
My aim is to decode that to according Swift struct
s:
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"
}
}
Thanks to the answer in my original question, I can now decode Player
s and Game
s successfully, but only when the response String
I use is the inner array, e.g.
:
let playersResponse = """
[
{
"id": 1,
"name": "John Doe"
},
{
"id": 15,
"name": "Jessica Thump"
}
]
"""
let players = try! JSONDecoder().decode([Player].self, from: playersResponse.data(using: .utf8)!)
The question
How can I extract only the JSON "players"
array from /common
's API response, so that I can feed it afterwards to a JSON decoder for my Player
s?
Please note that I can't use (or that's at least what I think) the "usual" Decodable
way of making a super-Struct
because I need players
to be decoded before games
(that was the topic of the original question). So, this doesn't work:
struct ApiResponse: Decodable {
let data: ApiData
}
struct ApiData: Decodable {
let players: [Player]
let games: [Game]
}
let data = try! JSONDecoder().decode(ApiResponse.self, from: rawApiResponse.data(using: .utf8)!)
What I tried so far
I looked into how to convert a JSON string to a dictionary but that only partially helped:
let json = try JSONSerialization.jsonObject(with: rawApiResponse.data(using: .utf8)!, options: .mutableContainers) as? [String:AnyObject]
let playersRaw = json!["data"]!["players"]!!
If I dump playersRaw
, it looks like what I want, but I have no clue how to cast it to Data
to pass it to my JSONDecoder
, as type(of: playersRaw)
is __NSArrayM
.
I feel like I'm not doing things the way they should be done, so if you have a more "Swifty" solution to the general problem (and not specifically to how to extract a subset of the JSON data), it would be even nicer!