Waldo sessions now support scripting! – Learn more
App Development

Getting Started With SwiftyJSON

Nabendu Biswas
Nabendu Biswas
Getting Started With SwiftyJSON
January 17, 2023
10
min read

JavaScript Object Notation (JSON) is the most common way for data transfer on the internet. Whether you're using a web app or a mobile app, the data from the back end will always come as JSON.

Most of the time, the back-end engineers use a framework like NodeJS (JavaScript), SpringBoot (Java), or .NET(C#) to create an API endpoint. The API endpoints interact with the database.

Now, from the web app front end, we use a library like Axios to make the API call. Meanwhile, from an iOS app, we use the library of Alamofire to do the API call.

Alamofire doesn't have any problem, but Swift is a strongly typed language that requires a lot of complex code for JSON. So, the data we get from Alamofire needs a lot of modification before being usable.

We've faced the same issue in our guide to Alamofire.

In this post, we'll first look into a solution to the JSON issue using SwiftyJSON. Then, we'll create a small project and learn to use SwiftyJSON on both locally stored JSON and JSON we get from Alamofire.

What Is SwiftyJSON?

SwiftyJSON is a completely open-source and free-to-use library that helps to format JSON in an easy and usable format.

Since Swift is a strongly typed language, it requires us to provide the data types of each JSON key. Aside from this, most of the time we need to create a model separately and give the types for each key.

Also, we need functions like JSONDecoder() to decode the JSON. We'll check out this problem later in the post.

SwiftyJSON provides an easy-to-use function called JSON through which we can easily get the data in the required format.

Project Setup

Let’s first create a new project by opening XCode. After that click on New > Project.

SwiftyJSON Screenshot 1

In the next pop-up, click on App and then the Next button.

SwiftyJSON Screenshot 2

In the new pop-up, give any product name. We'll give it the name SwiftyJSONdemo. The interface should be Storyboard because we’re going to use Storyboard in our app.

We'll also include tests because we're going to test our app.

SwiftyJSON Screenshot 3

In the next pop-up, click on the Create button after choosing a suitable folder.

SwiftyJSON Screenshot 4

Our project will open in XCode, and it'll look like this:

SwiftyJSON Screenshot 5

Installing Dependencies of SwiftyJSON Through Podfile

Now, let's install the dependencies of SwiftyJSON in our project. We're also going to install the dependency of Alamofire in our project because we're going to use it to do API calls.

The best way to install both of them is through Cocopods. However, the latest version of XCode has some issues on the latest Mac running M1 chips. Therefore, we'll change the project format to XCode 13.0-compatible.

SwiftyJSON Screenshot 6

Now, in the project directory, run the pod init command from the terminal. This will create a Podfile, which can be seen in the terminal through the ls command.

SwiftyJSON Screenshot 7

Next, from the terminal, to open the file in TextEdit, give the command open Podfile. Here, add the line pod 'Alamofire' with the correct spaces. To save the file, press Cmd + S and then close it.

SwiftyJSON Screenshot 8

Then, from the terminal, run the pod install command. This command will install Alamofire in our project.

SwiftyJSON Screenshot 9

Now, let's again open the Podfile and add the line pod 'SwiftyJSON', '~> 4.0' with the correct spaces. We got this command from the SwiftyJSON GitHub page.

SwiftyJSON Screenshot 10

From the terminal, run the pod install command. This command will install SwiftyJSON in our project.

SwiftyJSON Screenshot 11

In the Finder, a new SwiftyJSONdemo.xcworkspace file with a white background will be created. To use the updated project with Alamofire and SwiftyJSON installed, open this new file with a white background in XCode.

SwiftyJSON Screenshot 12

Layout Through Storyboard

We'll create our app to parse JSON with the click of a button. To do so, click on the Main.storyboard file, which will show an image of an iPhone. After that, open the object library by clicking on the + sign in the upper-right corner.

Here, search for the button and click on Button. Then drag it to the iPhone image:

SwiftyJSON Screenshot 13

We've also expanded the button and given it the name Get JSON Data. Additionally, we've changed the background color.

SwiftyJSON Screenshot 14

Now, click on the Align icon on the bottom-right of the screen. Here, select both of the checkboxes and then the Add 2 Constraints button.

SwiftyJSON Screenshot 15

Next, we need to open an outlet in the project for the button. So, open the ViewController.swift file on another screen.

After that, press the Ctrl key and, with a pointer, drag the button to the ViewController file. Here, a pop-up will be opened that gives the outlet a name.

SwiftyJSON Screenshot 16

Parsing Locally Stored JSON

We'll first learn to parse a locally stored JSON. For this, we have a posts.json file that is an array of objects.


  [
      {
       "id": 1,
       "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
       "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
      },
      {
       "id": 2,
       "title": "qui est esse",
       "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
      },
      {
       "id": 3,
       "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
       "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
      },
      {
       "id": 4,
       "title": "eum et est occaecati",
       "body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
      },
      {
      "id": 5,
      "title": "nesciunt quas odio",
      "body": "repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque"
      },
     {
      "id": 6,
      "title": "dolorem eum magni eos aperiam quia",
      "body": "ut aspernatur corporis harum nihil quis provident sequi\nmollitia nobis aliquid molestiae\nperspiciatis et ea nemo ab reprehenderit accusantium quas\nvoluptate dolores velit et doloremque molestiae"
     }
    ]
SwiftyJSON Screenshot 17

We've dragged the file in our project inside the SwiftyJSONdemo folder. This will open a pop-up, where you can click on the Finish button.

SwiftyJSON Screenshot 18

Now, in the ViewController.swift file, we'll first import SwiftyJSON and Alamofire. After that, inside the button outlet, add the code below.

Here, we'll first use the posts.json file through a Bundle. After that, we'll use the Alamofire request to hit the JSON file.

In a switch case upon success, we reprint the data. Upon an error, we print the error.

We've also started the app on the simulator, which is showing the button.


 guard let fileLoc = Bundle.main.url(forResource: "posts", withExtension: "json")
      else {
        print("File Not found")
        return
      }
      AF.request(fileLoc).responseJSON { response in
         switch response.result {
           case .success(let data):
              print(data)
          case .failure(let error):
              print("Error Found \(error)")
         }
      }
SwiftyJSON screenshot 19

Upon pressing the Get JSON Data button, we'll get the data printed in the console. However, as seen, the data is not the array of objects and seems out of sync. It's also very difficult to get a value out of it.

SwiftyJSON screenshot 20

Next, we'll update our code in the ViewController.swift file to use the JSON function from SwiftyJSON. This function converts our JSON to an easy-to-use value.

Then, we'll use a for loop to go through our JSON data, which is stored in value. Here, we'll print the Title with value[i]["title"] and the Body with value[i]["body"].

These are exactly how you'll print an array of objects in other languages like JavaScript.

    
      let value = JSON(data)
      for i in 0...value.count-1 {
         print("Title - \(value[i]["title"])")
         print("Body - \(value[i]["body"])")
      }
    

SwiftyJSON screenshot 21

Now, upon running the app again, we'll get the data correctly in the console.

SwiftyJSON screenshot 22

Parsing API Data

In real apps, we don't use locally stored JSON data, but we get it from an endpoint. We'll take our data from the famous JSON placeholder endpoint.

The code that has been used is taken from our Alamofire post. Here, we'll use a longer form of Alamofire's (AF) function, in which we give different parameters including the URL.

Again, inside a switch statement, we'll get the result. But since the data is not in the correct format, we have to use JSONDecoder() to convert it into JSON.

Also, notice that we’re using a struct Model, which contains the exact fields from the JSON placeholder endpoint.


  let url = "https://jsonplaceholder.typicode.com/posts"
      AF.request(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil, interceptor: nil)
         .response{ resp in
           switch resp.result{
              case .success(let data):
                do{
                 let jsonData = try JSONDecoder().decode([Model].self, from: data!)
                 print(jsonData)
               } catch {
                 print(error.localizedDescription)
              }
             case .failure(let error):
               print(error.localizedDescription)
             }
      }
      
      ...
      struct Model:Codable {
        let userId: Int
        let id: Int
        let title: String
        let body: String
      }
SwiftyJSON screenshot 23

Even after all this, our data is not in the correct readable format, as shown in the console.

SwiftyJSON screenshot 24

So, we'll remove the complex JSONDecoder() and use the simpler JSON function again.


let value = JSON(data as Any) print(value)
SwiftyJSON screenshot 25

Now, upon running the app again, we'll get an easy-to-read output.

SwiftyJSON screenshot 26

Then, we'll again add the for loop from the earlier section to show the title and body.


  for i in 0...value.count-1 { 
        print("Title - \(value[i]["title"])") 
        print("Body - \(value[i]["body"])") 
     }
SwiftyJSON screenshot 27

And we'll again see the desired output in the console.

SwiftyJSON screenshot 28

Testing the App

Finally, we'll test our app with XCUITest in XCode. Refer to our post on XCUI methods to learn the setup for test cases.

For testing, we need the unique ID for an element. For this, we'll use the Accessibility Inspector to get the unique IDs. Just open it by clicking on XCode > Open Developer Tool > Accessibility Inspector.

After that, open the simulator on the side and use the pointer to click on the button. Then, we'll get its unique ID of Label as Get JSON Data.

SwiftyJSON screenshot 29

For testing, first, create the file SwiftyJSONTests.swift inside the Tests folder. Here, we'll create a jsonButton variable to get the element.

Next, we've created a tapButton function, which will tap on the button.


 import XCTest

      public class SwiftyJSONTests: BaseTest {
         override var rootElement: XCUIElement{
           return app.staticTexts["Get JSON Data"]
         }
      
         lazy var jsonButton = app.staticTexts["Get JSON Data"]
      
         @discardableResult
         func tapButton(completion: Completion = nil) -> Self {
           log("Get JSON Data button tap done")
           jsonButton.tap()
           return self
        }
      }
SwiftyJSON screenshot 30

Finally, in the BasicTests.swift file, we'll call the SwiftyJSONTests class and then the tapButton function:


SwiftyJSONTests().tapButton()
SwiftyJSON screenshot 31

Upon clicking on the play test button in the project, our test will pass. All our test cases ran successfully, and the logs also confirmed that.

SwiftyJSON screenshot 32

What We've Covered About SwiftyJSON

In this post, we talked about an easier way to parse JSON data using the SwiftyJSON library. We created a simple project in XCode and then parsed both the locally stored JSON file and the file from API using SwiftyJSON.

We also wrote simple test cases using XCUITest.

But writing test cases to test API calls used in the project can be very complex, as it requires mocking logic.

Instead of that, try Waldo, where you only need to provide the APK or IPA file. Then, just interact with the mobile app by pressing the button. Waldo will automatically generate test cases and email you the results.

Automated E2E tests for your mobile app

Waldo provides the best-in-class runtime for all your mobile testing needs.
Get true E2E testing in minutes, not months.

Reproduce, capture, and share bugs fast!

Waldo Sessions helps mobile teams reproduce bugs, while compiling detailed bug reports in real time.