How to parse JSON with Swift 4

How do you parse JSON with Swift 4? Maybe you’ve done it with Swift 3 before, and if you have, you’ll be pleased to know that it’s so much better in Swift 4. And guess what? Nobody even calls it parsing any more — it’s decoding now. Apple has some new classes and protocols we can use: JSONDecoder and Decodable for decoding from JSON data to a model object, and JSONEncoder and Encodable for encoding from a model object to JSON data.

Let’s look at how to parse — or decode — the JSON feed from roadfiresoftware.com, which you can see for yourself here. It looks something like this, though I’ve removed a bunch of JSON properties for the sake of simplicity:

{
  "home_page_url": "http://roadfiresoftware.com",
  "title": "Roadfire Software",
  "items": [
    {
      "id": "http://roadfiresoftware.com/2018/01/whats-the-best-way-to-learn-ios-development-with-swift/",
      "url": "http://roadfiresoftware.com/2018/01/whats-the-best-way-to-learn-ios-development-with-swift/",
      "title": "What’s the best way to learn iOS development with Swift?"
    },
    {
      "id": "http://roadfiresoftware.com/2018/01/how-to-write-a-singleton-in-swift/",
      "url": "http://roadfiresoftware.com/2018/01/how-to-write-a-singleton-in-swift/",
      "title": "How to write a singleton in Swift"
    }
  ]
}

We can decode this in just two steps: first, we’ll define our model objects, and then we’ll use JSONDecoder to transform JSON data into our models.

1. Defining model objects that conform to Decodable

If we wanted to take all that JSON and turn it into objects, we might have Blog and Article models to represent it. Here are those models:

struct Blog: Decodable {
    let title: String
    let homepageURL: URL
    let articles: [Article]

    enum CodingKeys : String, CodingKey {
        case title
        case homepageURL = "home_page_url"
        case articles = "items"
    }
}

struct Article: Decodable {
    let id: String
    let url: URL
    let title: String
}

Notice that both models conform to the Decodable protocol. This allows us to decode them later with JSONDecoder, a new Foundation class in Swift 4. Additionally, they’re both structs, which I generally prefer for model objects — but you can define classes instead if you like.

The other thing you probably noticed is that Blog has a strange new enum called CodingKeys with String as the raw type, and it conforms to the CodingKey protocol. This lets us map property names in our model to JSON keys when the names and keys aren’t the same. For us, this means that we can have a homepageURL property on our Blog that maps to the home_page_url key in JSON. And similarly for articles, we’re mapping to items in JSON.

Our Article model doesn’t need CodingKeys since all of the properties we want to map have names that match. The JSON id maps to the Article id, and the same goes for url and title.

2. Decoding JSON into model objects with JSONDecoder

And now that our models specify the mappings from JSON to Swift (and vice-versa), we just need to ask JSONDecoder to decode the data and transform it into a Blog.

guard let data = data else {
    print("Error: No data to decode")
    return
}

guard let blog = try? JSONDecoder().decode(Blog.self, from: data) else {
    print("Error: Couldn't decode data into Blog")
    return
}

print("blog title: \(blog.title)")
print("blog home: \(blog.homepageURL)")

print("articles:")
for article in blog.articles {
    print("- \(article.title)")
}

We start by verifying that we actually have data to decode. Then we use JSONDecoder‘s decode(_:from:) to transform that data into a Blog. And this is it — all we have to do is tell it that we want to turn this data into this type and all the magic happens under the hood. It prints the blog title, home, and a list of recent articles.

Conclusion

I hope this helps you to start working with JSON in Swift 4 — and furthermore, I hope you see that it’s relatively simple to do using the JSONDecoder class from the Foundation framework. So many people seem to want grab a third-party library to parse JSON, but for most use cases, I see very little benefit to using one to do something so simple — especially now that Swift 4 makes it so easy. You don’t need a third-party library for everything.

See all of this working live and tweak it to use your JSON endpoint by grabbing the playground for this article. Just drop your name and email in the boxes below and I’ll send you the playground right away.