In this tutorial, we will learn how to parse a JSON response in our iOS Application using Swift. We will display the parsed response in a UITableView. To know more about UITableView, check out this tutorial before proceeding ahead.
Swift JSON Parsing
JSON is the most commonly used format to send and receive data from the web services. The data is in the form of key-value pairs. Using Swift Dictionaries we can easily fetch the values from the keys.
In this tutorial, we’ll be parsing JSON data from a local resource file.
The JSONSerialization
class is used to parse a JSON data into a dictionary of key-value pairs by converting the Data
object.
The type of a JSON data is [String: Any]
.
Let’s create a single view iOS Application in which we’ll parse the data from a locally created JSON file into the TableView.
iOS JSON Parsing Example Project Structure
In the Main.storyboard we’ve added a label and a TableView to our ViewController.
We’ve set the TableView delegates to the ViewController.
For more info on how to set up a TableView using Storyboard, refer this tutorial.
Swift JSON Parsing Code
We will be parsing JSON data from the file. The response.json
file looks like this:
Serialising the data
let url = Bundle.main.url(forResource: "response", withExtension: "json")
guard let jsonData = url else{return}
guard let data = try? Data(contentsOf: jsonData) else { return }
guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else{return}
In the above code, we fetch the file over the Bundle.main.url
instance.
The Data instance converts it into a Data format which is then serialized as JSON.
Fetching data from the JSON instance
Now that we’ve got the JSON instance, we can fetch the data in the following manner:
if let dictionary = json as? [String: Any] {
if let title = dictionary["title"] as? String {
labelHeader.text = title
}
if let year = dictionary["year"] as? Double {
print("Year is (year)")
}
if let more_info = dictionary["more_info"] as? Double {
//This doesn't get printed.
print("More_info is (more_info)")
}
for (key, value) in dictionary {
print("Key is: (key) and value is (value)" )
}
}
In the TableView, we’ll populate another JSON file :
ViewController.swift
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var labelHeader: UILabel!
@IBOutlet weak var tableView: UITableView!
var movieList = [MarvelData]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = Bundle.main.url(forResource: "response", withExtension: "json")
guard let jsonData = url
else{
print("data not found")
return
}
guard let data = try? Data(contentsOf: jsonData) else { return }
guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else{return}
if let dictionary = json as? [String: Any] {
if let title = dictionary["title"] as? String {
labelHeader.text = title
}
if let year = dictionary["year"] as? Double {
print("Year is (year)")
}
if let more_info = dictionary["more_info"] as? Double {
//This doesn't get printed.
print("More_info is (more_info)")
}
for (key, value) in dictionary {
print("Key is: (key) and value is (value)" )
}
}
//Now lets populate our TableView
let newUrl = Bundle.main.url(forResource: "marvel", withExtension: "json")
guard let j = newUrl
else{
print("data not found")
return
}
guard let d = try? Data(contentsOf: j)
else { print("failed")
return
}
guard let rootJSON = try? JSONSerialization.jsonObject(with: d, options: [])
else{ print("failedh")
return
}
if let JSON = rootJSON as? [String: Any] {
labelHeader.text = JSON["title"] as? String
guard let jsonArray = JSON["movies"] as? [[String: Any]] else {
return
}
print(jsonArray)
let name = jsonArray[0]["name"] as? String
print(name ?? "NA")
print(jsonArray.last!["year"] as? Int ?? 1970)
for json in jsonArray
{
guard let movieName = json["name"] as? String else{ return }
guard let movieYear = json["year"] as? Int else{ return }
movieList.append(MarvelData(movieName: movieName, movieYear: movieYear))
}
self.tableView.reloadData()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return movieList.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let currentMovie = movieList[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
cell.textLabel?.text = currentMovie.movieName
cell.detailTextLabel?.text = "(currentMovie.movieYear)"
return cell
}
}
struct MarvelData {
let movieName: String
let movieYear: Int
public init(movieName: String, movieYear: Int) {
self.movieName = movieName
self.movieYear = movieYear
}
}
In the above code, we’ve parsed the second json file as well and appended each of the JSON Array elements into the array which holds the structures.
To display this data we must call reloadData()
over the tableView instance.
We can make the code that sets the json values in the structure instances much better.
struct MarvelData {
var movieName: String
var movieYear: Int
init(_ dictionary: [String: Any]) {
self.movieName = dictionary["name"] as? String ?? "NA"
self.movieYear = dictionary["year"] as? Int ?? 1970
}
}
Doing this we can change our :
guard let movieName = json["name"] as? String else{ return }
guard let movieYear = json["year"] as? Int else{ return }
movieList.append(MarvelData(movieName: movieName, movieYear: movieYear))
to
movieList.append(MarvelData(json))
Instead of iterating over the jsonArray using a for loop, we can easily use the handy operator concatMap in Swift. So this:
for json in jsonArray
{
movieList.append(MarvelData(json))
}
Changes to
movieList = jsonArray.compactMap{return MarvelData($0)}
//or
movieList = jsonArray.compactMap{MarvelData($0)}
//or
movieList = jsonArray.compactMap(MarvelData.init)
This is the power of Swift!
The output of the above application in action is:
This brings an end to this tutorial. You can download the project from the link below.