Juan Rangel
Juan Rangel

Reputation: 1793

Access Nested Data in Swift

I am accessing an API and decoding the json response into a User object, but I am attempting to change the JSON API strcuture. If I return a basic JSON object using this code

let httpURL = "https://dev.test/api/user"

var request = URLRequest(url: url)

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in

            guard let data = data else {return}

            do {
                let user = try JSONDecoder().decode(User.self, from: data)

                DispatchQueue.main.async {
                    print(user.email)
                }
            } catch let jsonErr {
                print(jsonErr)
            }
        }
        task.resume()

and the following JSON

{
    "id": 2,
    "email": "[email protected]",
}

This works fine, but I want to changed the API to return a set of nested objects. For example

{
  "data": {
    "user": {
      "id": 2,
      "email": "[email protected]"
    },
    "notifications": [
      {
        "id": "123",
        "notifiable_type": "App\\User"
      }
    ]
  }
}

How can I decode the User? I've tried several variations of this let user = try JSONDecoder().decode(User.self, from: data.data.user) and let user = try JSONDecoder().decode(User.self, from: data["data"]["user"])

bt

Upvotes: 0

Views: 275

Answers (1)

Shehata Gamal
Shehata Gamal

Reputation: 100503

You can try

struct Root: Codable {
    let data: DataClass
}

struct DataClass: Codable {
    let user: User
    let notifications: [Notification]
}

struct Notification: Codable {
    let id, notifiableType: String

    enum CodingKeys: String, CodingKey {
        case id
        case notifiableType = "notifiable_type"
    }
}

struct User: Codable {
    let id: Int
    let email: String
}

let user = try JSONDecoder().decode(Root.self, from:data)

OR

do {

    let con = try JSONSerialization.jsonObject(with:data, options: [:]) as! [String:Any]
    let data = con["data"] as! [String:Any]
    let user = data["user"] as! [String:Any]
    let finData = try JSONSerialization.data(withJSONObject:user, options: [:])
    let userCon = try JSONDecoder().decode(User.self, from:finData) 
    print(userCon)

}
catch {

    print(error)
}

Upvotes: 2

Related Questions