What does parsing JSON

Parsing JSON using the Codable protocol

JSON - short for JavaScript Object Notation - is a way of describing data. It's not exactly the most readable format, but it's compact and easily parsed by computers, making it popular online where bandwidth is precious.

Before we start parsing, here is a tiny snippet of the actual JSON that you will receive:

In fact, you will get 2,000-3,000 lines of this stuff containing petitions from US citizens about all sorts of political issues. It is actually not important (to us) what the petitions are about, we are only interested in the data structure. Especially:

  1. There is a metadata value that contains a value named, which in turn contains a status value. With status 200 my internet developer means that "everything is OK".
  2. There is a result value that contains a number of petitions.
  3. Each petition has a title, body text, some issues to which it relates, and information about the signatures.
  4. JSON also has strings and integers. Notice how quotation marks surround all strings, but not integers.

Swift has built in support for JSON with a protocol called. If you say, "my data is enough," Swift will allow you to freely convert between that data and JSON with just a little code.

Swift's simple types like and automatically suffice, and arrays and dictionaries suffice if they contain objects. That means, it is enough without any problems, because itself is enough.

Here, however, we need something more complex: each petition contains a title, a body of text, the number of signatures, and more. That means we need to define our own bespoke data type instead of just using or.

Swift has two ways of creating its own data types known as structs and classes. We've used classes before - all of our subclasses are classes - but if you're working with your own data rather than creating a subclass, structs are generally better to work with as they are simpler.

We will create our own struct that will contain a petition from our JSON, that is, it will store the title string, the body string, and the number of signatures, an integer. So press Cmd + N and choose a new Swift file called Petition.swift.

This defines a special struct with three properties. One of the great things about structs in Swift is that they give us a element-wise initializer give - a special function that can create new instances by passing values ​​for, and.

We'll get to that in a moment, but first I mentioned the protocol. Our struct contains two strings and an integer, all of which already suffice, so we can tell Swift that the whole -type should satisfy, like this:

With this simple change, we're almost ready to load instances of JSON.

I say nearly so far, because there is still a small catch in our plan: if you looked at the JSON example given above, you noticed that our petitions array is actually within a dictionary called "results". That means if we try to have Swift parse the JSON we have to load the key first, and then in this load the array of petition results.

Swift's protocol needs to know exactly where to find the data, which in this case means a second To make struct. This will have a single property called which is an array of our -Structs. This then fits exactly what JSON looks like: the main JSON contains the array, and in every element in that array there is a.

So press Cmd + N again to create a new file, choose Swift File and name it Petitions.swift. Give her this content:

I can see that this looks like a lot of work, but trust me, it will be a lot easier!

All we did was define the data structures that we want to load the JSON into. The next step is to create a property in that will store our petitions array.

As you will remember, you declare arrays by simply writing the data type in square brackets, like this:

We want to make an array out of our object. It will look like that:

Use it to replace the current definition at the beginning of ViewController.swift.

Now is the time to parse JSON, which means process it and examine the contents. We'll start by customizing the method for so that it downloads the data from the White House petitions server, converts it to a Swift object, and then tries to convert that into an array of instances.

We haven't used it yet. How and is this one of the fundamental data types of Swift, even if it is at an even lower level - it literally contains binary data of some kind. It could be a string, it could be the contents of a zip file, or literally anything else.

and have some things in common. You have already seen that one can be created using to load data from the hard drive, and it has exactly the same initializer. Both can therefore be generated with an initializer that downloads data from a URL (also specified) and makes it available to you.

That's perfect for our purposes - here's the new method:

Let's focus on the new:

  • refers to the Whitehouse.gov server to access the petitions system.
  • We use it to make sure that the is valid instead of forcing it to unpack ("force unwrap").
  • We create a new object using the method. This returns the content of a, but can also throw an error (for example, if there is no internet connection), so we have to use.
  • If the object was created successfully, we reach the line "we're OK to parse". It begins with, which is used to denote a comment line in Swift. Comment lines are ignored by the compiler; we write them as notes for ourselves.

This code is not perfect, on the contrary. By loading data from the Internet, our app is effectively blocked until all data has been transferred. There are solutions to this, but to keep it simple, we will only cover these in Project 9.

For now, let's focus on parsing JSON. We already have an array ready to hold an array of petitions. We want to use Swift's system to parse our JSON into the array and once that's done we tell our table view to reload itself.

Are you ready? Because this code is amazingly simple for the amount of work it does:

Place the method directly below the method, then replace the line in with this:

The new method does some new and interesting things:

  1. It creates an instance of that is specially designed to convert between JSON and objects.
  2. It then calls the method of this decoder to convert our data into an object. This call can throw an error, so we'll use to see if it worked.
  3. If the JSON has been converted successfully, we assign the array to our property and reload the table view.

The part you haven't seen before is what Swift's way of referring to the type directly rather than an instance of it. That is, we don't say "create a new one", but instead specify it as a parameter for decoding so that it knows what to convert the JSON to.

You can run the program now, even if it just keeps showing "Title goes here" and "Subtitle goes here", because our method only adds placeholder data.

We want to modify this so that the cells output the value of our object, but we also want to use the subtitle text label that came with when we changed the cell type in the storyboard from "Basic" to "Subtitle". To do this, change the method as follows:

We set the keys, and in the object, so we can now read them out in order to configure our cell correctly.

If you run the app now, you'll see how things fit together nicely - each row in the table now shows the title of the petition, and below that are the first few words of the body of the petition. The subtitle will automatically display "..." at the end if there is not enough space for all of the text, but that is enough to give the user an idea of ​​what it is about.

Sponsor Hacking with Swift and reach the world's largest Swift community!