Easily handle JSON in Swift with SwiftyJSON

Handling data is a common task for frontend developers, and the data is very often in JSON format. SwiftyJSON is an open source third-party library that is useful for handling JSON data easily in Swift. As of this writing, the package has 21K+ stars on GitHub and has been maintained since its initial release in 2014. It supports the latest versions of Swift, Xcode, and iOS. So far, it has met all my needs.

In this article, we’ll review how to handle JSON data easily in Swift with SwiftyJSON. We’ll use a demo project with a macOS command line interface to walk through the tutorial.

For the examples used in this article, we’ll use Swift v5, Xcode v13.2.1, and SwiftyJSON v5.0.1.

Let’s get started!

Creating a macOS CLI

Since a user interface is not important for this project, we’ll create and use a macOS command line tool. To create a CLI for macOS, open Xcode and click on Create a new Xcode project. Next, under macOS, select Command Line Tool, then click Next, and follow the remaining instructions.

Command Line Tool

Setting up the demo project

I like Pokémon, so I’ve decided to use it as the project’s topic. In this project, we’ll use the RESTful Pokemon API. We’ll request data for the character, Charmander, by fetching this JSON: https://pokeapi.co/api/v2/pokemon/charmander.

This article will focus on handling JSON, so we’ll skip over the process of requesting the JSON data.

For this demo, I’ve used the macOS URLSession to handle the HTTP requests, but you may also use Alamofire or Moya. In addition, you can always access the code in my GitHub repository. After we get the data, we’ll request some of Charmander’s attributes (for example, name, abilities, and type) and then we’ll display them in the terminal output.

The terminal output will look like this:

Terminal Output

Let’s get started.

Charmander Plush on Bench

Photo by Akin Cakiner on Unsplash.

Adding SwiftyJSON to the demo project

To use a third-party library, we need to import that package in our project. Therefore, our first step is to add the SwiftyJSON package to our project; we’ll use the Swift Package Manager.

Here’s our path: Xcode > ( Xcode project name) > Targets > (Xcode project name).

In the General tab, under the Frameworks and Libraries dropdown, we click on + and select Add package dependency. Then, we enter the package Git URL: https://github.com/SwiftyJSON/SwiftyJSON.git.

After the package is successfully added, we’ll see SwiftyJSON listed under Framework, as well as under Package Dependencies in the Project Navigator:

SwiftyJSON Under Framework

Using SwiftyJSON to parse JSON in Swift

Now, we’re ready to write some code. To start, we’ll use a snippet from our JSON data:

"name": "charmander",
"order": 5,
"past\_types": \[\],
...

We’ll create a JSON object that includes the name attribute of the data. Then, we’ll create a function to get the name attribute so that we can access it:

func getName(data: Data) {
    if let json = try? JSON(data: data) {
        let name = json\["name"\].string ?? "N/A"
        print("Name: \\(name)")
    }
}

When we call the getName function, we get the following output:

Name: **charmander**

Now, let’s work with the nested JSON from our Charmander HTTP request:

"abilities": \[
    {
      "ability": {
        "name": "blaze",
        "url": "<https://pokeapi.co/api/v2/ability/66/>"
      },
      "is\_hidden": false,
      "slot": 1
    },
    {
      "ability": {
        "name": "solar-power",
        "url": "<https://pokeapi.co/api/v2/ability/94/>"
      },
      "is\_hidden": true,
      "slot": 3
    }
  \], 
{...}

We’ll create a function to get the abilities attribute from the Charmander data. Previously, we created a JSON object, but now we have an array of objects. We’ll need to trace through the abilities array and get the name attribute of each ability.

func getAbilities(data: Data) {
    if let json = try? JSON(data: data) {
        for (\_, abilities) in json\["abilities"\] {
            let ability = abilities\\\["ability"\\\]\["name"\].string ?? "N/A"
            print("Ability: \\(ability)")
        }
    }
}

When we call the getAbilities function, we get the following output:

Ability: **blaze**

Ability: **solar-power**

Similar to abilities, we also have the types attribute. Then, inside the object, we have a type object with a name attribute. We can see both attributes in the below JSON snippet:

"types": \[
    {
      "slot": 1,
      "type": {
        "name": "fire",
        "url": "https://pokeapi.co/api/v2/type/10/"
      }
    }
  \]

Now, we’ll trace through the types array and get the name attribute of each type.

func getType(data: Data) {
    if let json = try? JSON(data: data) {
        for (\_, types) in json\["types"\] {
            let type = types\\\["type"\\\]\["name"\].string ?? "N/A"
            print("Type: \\(type)")
        }
    }
}

When we call the getType function, we get the following output:

Type: **fire**

Addressing type issues in Swift

In Swift, we have to use explicit typing. The benefit of this is that we are less likely to make mistakes. The downside is that it is not very flexible.

For example, when we fetch JSON data, we create the attributes by declaring their data type. If the data type changes from the server side, we’ll be unable to parse the JSON data and the app will crash. Fortunately, SwiftyJSON helps us address this issue.

Let’s look at an example.

In the below code snippet, we specify that the data type is a string. We could also specify that it must be an integer; the point here is that the code indicates it must be of the type we are specifying.

let ability = abilities\\\["ability"\\\]\["name"\].string!

In this example, as long as the data type actually is a string, everything is fine. But if the data type changes, the value becomes nil and the app will crash.

Now, let’s look at the same example, but this time we’ll use a nil-coalescing operator to accomodate any possible changes in data type:

let ability = abilities\\\["ability"\\\]\["name"\].string ?? "N/A"

In the above snippet, we check to see if the data type is a string. If it is not a string, the value “N/A” is returned. The app does not crash. Of course, you are not limited to “N/A”, you may use any designation you like.

Conclusion

In this article, we reviewed how to handle JSON in Swift with SwiftyJSON and discussed how to handle type issues. We walked through the article examples using a demo with a macOS command line interface.

I hope you’ve enjoyed this article. Go to GitHub to check out the sample project that I made for this article. Feel free to reach out to me at or in the below comment section. I appreciate your valuable feedback. Take care!

The post Easily handle JSON in Swift with SwiftyJSON appeared first on LogRocket Blog.