Reputation: 5252
I am using Swift for the first time and I'd like to be able to process some info from an API response into a usable Swift object.
I have (for example) the following data coming back from my API:
{
data: [{
id: 1,
name: "Fred",
info: {
faveColor: "red",
faveShow: "Game of Thrones",
faveIceCream: "Chocolate",
faveSport: "Hockey",
},
age: "28",
location: "The Moon",
},{
...
}]
}
In swift I have the data
coming back from the API. I get the first object and I'm converting it and accessing it like so:
let json = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
let dataParentNode = json["data"] as! [[String:Any]]
let firstObject = dataParentNode[0]
let _id = firstObject["id"] as? String ?? "0"
let _name = firstObject["name"] as? String ?? "Unknown"
This is fine until I want to start processing the sub-objects belonging to the first object so I came up with the following struct
s to try and make this cleaner.
Please note - I don't need to process all of the JSON data coming back so I want to convert it to what I need in the structs
struct PersonInfo : Codable {
let faveColor: String?
let faveShow: String?
}
struct Person : Codable {
let id: String?
let name: String?
let info: PersonInfo?
}
When I take this:
let json = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
let dataParentNode = json["data"] as! [[String:Any]]
let firstObject = dataParentNode[0]
and then try to convert firstObject
to Person
or firstObject["info"]
to PersonInfo
I can't seem to get it to work (I get nil
).
let personInfo = firstObject["info"] as? PersonInfo
Can anyone advise please? I just need to get my head around taking API response data and mapping it to a given struct (with sub-objects) ignoring the keys I don't need.
Upvotes: 1
Views: 672
Reputation: 8347
You can simply use decode(_:from:)
function of JSONDecoder
for this:
let decoder = JSONDecoder()
do {
let decoded = try decoder.decode([String: [Person]].self, from: data)
let firstObject = decoded["data"]?.first
} catch {
print(error)
}
Even better you can add another struct to you model like this:
struct PersonsData: Codable {
let data: [Person]
}
And map your JSON using that type:
let decoder = JSONDecoder()
do {
let decoded = try decoder.decode(PersonsData.self, from: data)
let firstObject = decoded.data.first
} catch {
print(error)
}
Update: Your Person struct might need a little change, because the id property is integer in your JSON.
So, it will end up like this:
struct Person : Codable {
let id: Int?
let name: String?
let info: PersonInfo?
}
Upvotes: 1