Access nested JSON object - Swift

I have three endpoints which all display an array of JSON data. I want to 'GET' the contents and populate it on a table view. how do i use struct or class methods to get a nested key between url links. I am trying to decode 'userId' in the posts url to display the users details in the users url.

These are the url links;

http://jsonplaceholder.typicode.com/posts

http://jsonplaceholder.typicode.com/users

http://jsonplaceholder.typicode.com/comments


I have given some JSON data but i would like to access the whole array.

http://jsonplaceholder.typicode.com/posts

[ {
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et ***\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
} ]


http://jsonplaceholder.typicode.com/users
[ {
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
} ]
http://jsonplaceholder.typicode.com/comments
[ {
"postId": 1,
"id": 1,
"name": "id labore ex et quam laborum",
"email": "Eliseo@gardner.biz",
"body": "laudantium enim quasi est quidem magnam voluptate ipsam eos\ntempora quo necessitatibus\ndolor quam autem quasi\nreiciendis et nam sapiente accusantium"
} ]


This is what i have so far -


import Foundation

var allUsers = [Users]()
var allPosts = [Posts]()

class Posts: Codable {
let userId: Int
let id: Int
let title: String
let body: String
}
class Users: Codable {
let id: Int
let name: String
let username: String
}
let postURL = URL(string: "https://jsonplaceholder.typicode.com/posts")
let userURL = URL(string: "https://jsonplaceholder.typicode.com/users")
//let jsonData = try! Data(contentsOf: postURL!)
func parseJSON(){
URLSession.shared.dataTask(with: postURL!) { (data, response, error) in
guard let data = data else { print("error with data"); return }
do {
allPosts = try JSONDecoder().decode([Posts].self, from: data);
//interupt the main thread and update the table with the retrieved data
dump(allPosts)
} catch let err {
print("Error: ", err)
}
}.resume() // start the network call
URLSession.shared.dataTask(with: userURL!) { (data, response, error) in
guard let data = data else { print("error with data"); return }
do {
allUsers = try JSONDecoder().decode([Users].self, from: data);
//interupt the main thread and update the table with the retrieved data
dump(allUsers)
} catch let err {
print("Error: ", err)
}
}.resume() // start the network call
}


And i am calling the function parseJSON in view controller.

Replies

First of all, I suggest you don't use "URLSession.shared" here, but instead create your own session like this:


let urlSession = URLSession(configuration: URLSessionConfiguration.default, delegate: nil, delegateQueue: .main)


This helps by telling the session to invoke all dataTask completion handlers for this session on the main queue, which means you don't have to worry about thread safety issues ("interrupt the main thread") when you update the data for the table view.


Second, I suggest you arrange the code in your completion handlers so that you don't make any new data available to the table view until retrieval and decoding of both the posts and users arrays are complete.


Third, you will need to create a new pair of custom classes, one for posts, and one for users, that will be similar to Posts and Users, except that the new post class will have a reference to a user instance, instead of a numeric user id. That's how you would get your nesting.


Fourth, if you're careful, you can actually re-use Posts and Users for the both the original data and the new nested data, if you provide a custom implementation for Codable in the Posts and Users.


Finally, remember that the Posts and Users types each represent one thing (one post or one user). Those classes would be better called Post and User! 🙂

Thank you for taking the time to look at this. I've been stomped for a while trying to figure this out. I will get back to you with an update on my application 🙂