Parsing JSON into objects is a core part of object orientated programming. Almost every application relies on using a process to decode JSON safely. In Swift now, Apple has provided a mechanism to help simplify this process for developers.

Swifts Codable protocol maps the coding keys on your object models to the JSON that has been retrieved. This means that developers have to write very little code in the process. We only have to ensure that our coding keys map correctly to the values we are expecting in our JSON.

Tutorial:

We are going to make a simple app that uses the Decodable protocol to create Article objects from New York Times’ free article API. It is time to start off with a new single view application and create a UITableView inside your first ViewController.

If you would like to access the New York Times’ free API you will need to register here:

https://developer.nytimes.com

After you have registered you will be given an API key, which you will need to attach to the API call in the Networking class we will build later.

We are going to start the project by building the model file. This is going to be the structure that our Article will be created from with the JSON that we retrieve from the New York Times API. We are going to define two structures in this file, one will be Articles (plural) and one will be Article (singular).

Our JSON will be decoded into Articles, which is simply the number of articles in an Integer and an array of Articles. One important thing to remember when using Codable and Decodable protocols is that all of the objects inside the Decodable object must also be Decodable. This means our Article struct also has to be Decodable.

Now inside our structs, we are going to define our coding keys. These are the strings that will map our JSON values into our objects properties.


// MARK: Frameworks
import Foundation
// MARK: Article
struct Articles: Decodable {
let count: Int
let results: [Article]
enum CodingKeys: CodingKey, String {
case count = "num_results"
case results = "results"
}
}
// MARK: Article
struct Article: Decodable {
let articleId: Int
let title: String
let url: URL
enum CodingKeys: CodingKey, String {
case articleId = "id"
case title = "title"
case url = "url"
}
}

view raw

Article.swift

hosted with ❤ by GitHub

Next, we want to create our ArticleRemote class, this is going to contain our networking code. By putting your networking code into a separate class it will tidy up your view controllers.

Inside our ArticleRemote class, we just have one static function that will retrieve our Articles in JSON. Once the network call has been completed and we are sure there are no errors we can instantiate a JSONDecoder object, this will decode the JSON into our Articles object.


// MARK: Frameworks
import Foundation
// MARK: ArticleRemote
class ArticleRemote {
static func retrieveArticles(completion: @escaping(_ articles: Articles) -> Void) {
let session = URLSession(configuration: .default)
let apiURL: URL = URL(string: "https://api.nytimes.com/svc/mostpopular/v2/mostviewed/Technology/1.json")!
var request: URLRequest = URLRequest(url: apiURL)
request.addValue("245f0d40c8d64f07bfe69265569e34a9", forHTTPHeaderField: "api-key")
let task = session.dataTask(with: request) { (data, response, error) in
guard error == nil, let data = data else {
return
}
let decoder = JSONDecoder()
do {
let articles = try decoder.decode(Articles.self, from: data)
completion(articles)
} catch let error {
print("Error: \(error)")
}
}
task.resume()
}
}

Now we can fill our ArticleViewController with the code required to display the Articles that we have now created using our remote request. We are simply going to display the title for each article and give the ability for the user to tap the cell and be taken to the article.


// MARK: Frameworks
import UIKit
// MARK: ArticleViewController
class ArticleViewController: UIViewController {
// MARK: Outlets
@IBOutlet var myTableView: UITableView!
// MARK: Variables
var articles: [Article] = []
// MARK: View Methods
override func viewDidLoad() {
super.viewDidLoad()
ArticleRemote.retrieveArticles { articles in
self.articles = articles.results
DispatchQueue.main.async {
self.myTableView.reloadData()
}
}
}
}
// MARK: UITableViewDataSource Methods
extension ArticleViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return articles.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "Cell")
let article = articles[indexPath.row]
cell.textLabel?.text = article.title
return cell
}
}
// MARK: UITableViewDelegate Methods
extension ArticleViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let article = articles[indexPath.row]
openURL(article.url)
}
// MARK: Helper Methods
private func openURL(_ url: URL) {
guard UIApplication.shared.canOpenURL(url) == true else {
return
}
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}

The last thing we want to do is connect up our ArticleViewController to the storyboard. We need to create a UITableView that is constrained to the edges and connect it up to the outlet, datasource, and delegate for the UIViewController.

Screen Shot 2018-04-08 at 12.39.47 PM

If you build and run your project now you should get a live list of the latest Technology articles fresh from the New York Times!

Simulator Screen Shot - iPhone 8 Plus - 2018-04-08 at 14.02.54

The source code for the finished codable example project is available here:

https://github.com/rtking1993/CodableTests

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.