1

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 structs 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.

3
  • let personInfo = firstObject as? PersonInfo, firstObject as? PersonInfo is nil, because firstObject isn't cartable as a PersonInfo, it's a Dictionary at best. let personInfo = PersonInfo(faveColor: firstObject["faveColor"] as? String ?? "Unknown color", faveShow: firstObject["faveColor"] as? String ?? "Unknown show") Commented Oct 15, 2020 at 10:33
  • @Larme - sorry that was a typo. firstObject is the first result in the array from data in the JSON so it should be: let personInfo = firstObject["info"] as? PersonInfo in my OP Commented Oct 15, 2020 at 10:37
  • let personInfoDict = firstObject["info"] as? [String: Any], and let personInfo = PersonInfo(faveColor: personInfoDict["faveColor"] as? String ?? "Unknown color", faveShow: personInfoDict["faveColor"] as? String ?? "Unknown show") Commented Oct 15, 2020 at 10:39

1 Answer 1

1

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?
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks again for this. This was the answer for me. I'd tried doing something similar but still got an error. Turns out I didn't note a potential variation in the API response which I needed to cover. All working now and much cleaner code!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.