JSON or JavaScript Object Notation is a lightweight data interchange format that is used for sending and receiving structured data over the internet. It’s become increasingly popular in recent years, and is the preferred choice for representing structured data when compared to other formats like XML. If you’re writing mobile applications in Swift, you’ll need to know how to parse JSON data in your code. In this article, we’ll discuss what JSON is and how to parse it in Swift, as well as some of the best practices for successful parsing.
What is JSON?
JSON defines a syntax for creating objects, arrays, and other data structures. It directly translates to code and is often preferred for transferring data between applications or web services because of its light weight and easy-to-read syntax. For example, the following data structure represents a simple book object:
{ "title": "The Hobbit", "author": "J.R.R. Tolkien" }
In this instance, “title” is an object key and “The Hobbit” is the value assigned to it. Similarly, the “author” object key has the value “J.R.R. Tolkien” assigned to it.
Benefits of JSON
Using JSON has several advantages over other data formats:
- Easy to Read: The syntax of JSON is straightforward and easy to understand, so it’s much easier to create and parse than other formats.
- Lightweight: Since JSON uses less data and is easy to read and parse, it’s much lighter than formats like XML. This makes it the perfect choice for transferring small amounts of data over the internet.
- Supported Everywhere: JSON is supported in almost all programming languages, so it can easily be used across platforms.
How to Parse JSON in Swift
Parsing JSON in Swift requires two steps: Decoding the data into an object, and mapping the object into a model. Decoding is done using the JSONDecoder class in Swift built-in support for JSON parsing. The unmarshalled data will be stored in a Dictionary object which you can use to access individual values as required.
As an example, let’s say we have the following JSON string:
{"name":"John", "age":34, "city":"New York"}
To parse this JSON string using his JSONDecoder class, we first need to define a data model that represents our data structure:
struct Person { let name: String let age: Int let city: String }
With our data model in place, we can now call the JSONDecoder’s decode method and pass it our JSON string, as well as our Person model:
let jsonString = "{\"name\":\"John\",\"age\":34,\"city\":\"New York\"}" let data = Data(jsonString.utf8) let person = try JSONDecoder().decode(Person.self, from: data) print(person.name) // John
JSON Syntax and Structure
JSON follows a syntax and structure that’s similar to other programming languages. It makes use of key-value pairs — like dictionaries — to represent data structures, as well as array structures to store multiple values.
Objects are written using curly brackets ({}
) and contain key-value pairs which are separated by commas (,
) while values are written as quoted strings. For example:
"name": "John"
Arrays are written using brackets ([]
) and contain a comma-separated list of values. For example:
[1,2,3,4,5]
Parsing Complex JSON Arrays in Swift
When working with complex arrays, you’ll often need to loop through each element to get the values that you need. This is done using the for-in loop in Swift.
As an example, let’s say we have an array of numbers represented as a string: [1,2,3,4,5]
. We can use the JSONDecoder class to decode this into an array of integers as follows:
let jsonString = "[1,2,3,4,5]" let data = Data(jsonString.utf8) let numbers = try JSONDecoder().decode([Int].self, from: data) for number in numbers { print(number) // 1 2 3 4 5 }
Parsing Nested JSON Objects in Swift
Sometimes you’ll need to parse nested objects that contain multiple levels of objects and arrays. This can be done by adding multiple models that correspond to each key and each level of nesting. The result will be a collection of nested structs that map directly to our data structure.
For example, let’s say we have the following JSON string:
{ "name": "John", "age": 34, "city": { "name": "New York", "population": 8_000_000 } }
To decode this we’ll need two models — one for our outer object (Person
) and one for the nested city object (City
). Here’s what they’ll look like:
struct Person { let name: String let age: Int let city: City } struct City { let name: String let population: Int }
Once we have our models defined, we can use the JSONDecoder class to decode this string into a Person object using the following code:
let jsonString = "{\"name\":\"John\",\"age\":34,\"city\":{\"name\":\"New York\",\"population\":8000000}}" let data = Data(jsonString.utf8) let person = try JSONDecoder().decode(Person.self, from: data) print(person.name) // John
Handling Errors While Parsing Json in Swift
When working with JSON parsing in code you’ll inevitably encounter errors. When this happens you won’t be able to successfully decode your data and will get an error message that describes what went wrong. It’s important that your code is able to correctly handle these errors.
The easiest way to do this is by using try-catch blocks so that you’re able to catch the error and manage it gracefully instead of just crashing. Here’s an example of how you would handle errors while decoding your Person object:
do { let person = try JSONDecoder().decode(Person.self, from: data) print(person.name) // John } catch { // Handle error gracefully here }
Best Practices for Parsing Json with Swift
When working with JSON parsing in Swift there are some best practices that you should adhere to in order to ensure success:
- Know Your Data Source: Before parsing any JSON string you should always take a look at the source of the data to get a good understanding of its structure and any potential issues you may face.
Conclusion
JSON is an essential format for exchanging data between applications. Although it has an easy-to-read syntax, parsing complex structures in Swift requires care and attention to avoiding errors. By following best practices such as validating your model before attempting a parse and handling errors gracefully with try-catch blocks you can ensure your code is successful.