Encoding and Decoding in Swift

In this tutorial, you’ll learn all about encoding and decoding in Swift, exploring the basics and advanced topics like custom dates and custom encoding. By Cosmin Pupăză.

4.6 (54) · 1 Review

Download materials
Save for later
Share
Update note: Cosmin Pupăză updated this tutorial for Xcode 11, iOS 13 and Swift 5.1 Eli Ganem wrote the original.

A common task for iOS apps is to save data and send it over the network. But before you can do that, you need to convert the data to a suitable format through a process called encoding or serialization.

Example of data being encoded.

You’ll also need to convert the saved data sent over the network to a suitable format before using it in your app. This reverse process is called decoding or deserialization.

Example of data being decoded.

In this tutorial, you’ll learn all you need to know about encoding and decoding in Swift by managing your very own toy store. You’ll explore the following topics along the way:

  • Switching between snake case and camel case formats.
  • Defining custom coding keys.
  • Working with keyed, unkeyed and nested containers.
  • Handling nested types, dates, subclasses and polymorphic types.

There’s quite a lot to cover, so it’s time to get started! :]

Note: This tutorial assumes you have a basic knowledge of JSON. Check out this cheat sheet if you need a quick overview.

Getting Started

Download the starter playground using the Download Materials link at the top or bottom of the tutorial.

Make sure the Project navigator is visible in Xcode by going to View ▸ Navigators ▸ Show Project Navigator. Open Nested types.

Add Codable conformance to Toy and Employee:

struct Toy: Codable {
  ...
}
struct Employee: Codable {
  ...
}

Codable isn’t a protocol on it’s own, but an alias for two other protocols: Encodable and Decodable. As you might guess, those two protocols declare that types can be encoded to and decoded from a different format.

You don’t need to do anything more, because all the stored properties of both Toy and Employee are codable. Many basic types in the Swift Standard Library and Foundation types (for example, String and URL) are codable by default.

Note: You can encode codable types to various formats such as Property Lists (PLists), XML or JSON, but for this tutorial you’ll only work with JSON.

Add a JSONEncoder and a JSONDecoder to handle JSON encoding and decoding of toys and employees:

let encoder = JSONEncoder()
let decoder = JSONDecoder()

That’s all you need to work with JSON. Time for your first encoding and decoding challenge!

Encoding and Decoding Nested Types

Employee contains a Toy property — it’s a nested type. The JSON structure of your encoded employee matches the Employee struct:

{
  "name" : "John Appleseed",
  "id" : 7,
  "favoriteToy" : {
    "name" : "Teddy Bear"
  }
}
public struct Employee: Codable {
  var name: String
  var id: Int
  var favoriteToy: Toy
}

The JSON nests name inside favoriteToy and all the JSON keys are the same as the Employee and Toy stored properties, so you can easily understand the JSON structure based on your data types hierarchy. If your property names match your JSON field names, and your properties are all Codable, then you can convert to or from JSON very easily. You’ll try that now.

The Gifts department gives employees their favorite toys as birthday gifts. Add the following code to send your employee’s data to the Gifts department:

// 1
let data = try encoder.encode(employee)
// 2
let string = String(data: data, encoding: .utf8)!

Here’s how this code works:

  1. Encode employee to JSON with encode(_:) (I told you it was easy!).
  2. Create a string from the encoded data to visualize it.
Note: Press Shift-Return to run the playground up to your current line, or click the blue play button. To see results, you can print values to the debugger console or click the Show Result button in the results sidebar.

The encoding process generates valid data, so the Gifts department can recreate the employee:

let sameEmployee = try decoder.decode(Employee.self, from: data)

Here, you’ve used decode(_:from:) to decode data back to Employee… and you’ve made your employee very happy. Press the blue play button to run the Playground and see the results.

Time for your next challenge!

Switching Between Snake Case and Camel Case Formats

The Gifts department API has switched from camel case (which looksLikeThis) to snake case (which looks_like_this_instead) to format keys for its JSON.

But all of the stored properties of Employee and Toy use camel case only! Fortunately, Foundation has you covered.

Open Snake case vs camel case and add the following code just after the encoder and decoder are created, before they get used:

encoder.keyEncodingStrategy = .convertToSnakeCase
decoder.keyDecodingStrategy = .convertFromSnakeCase

Here, you set keyEncodingStrategy to .convertToSnakeCase to encode employee. You also set keyDecodingStrategy to .convertFromSnakeCase to decode snakeData.

Run the playground and inspect snakeString. The encoded employee looks like this in this case (pun intended):

{
  "name" : "John Appleseed",
  "id" : 7,
  "favorite_toy" : {
    "name" : "Teddy Bear"
  }
} 

The formatting in JSON is now favorite_toy and you’ve transformed it back to favoriteToy in the Employee struct. You’ve saved the (employee’s birth)day again! :]

Image of a dog announcing: Happy birthday!

Working With Custom JSON Keys

The Gifts department has changed its API again to use different JSON keys than your Employee and Toy stored properties use:

{
  "name" : "John Appleseed",
  "id" : 7,
  "gift" : {
    "name" : "Teddy Bear"
  }
}

Now, the API replaces favoriteToy with gift.

This means that the field names in the JSON will no longer match up with the property names in your type. You can define custom coding keys to supply coding names for your properties. You do this by adding a special enum to your type. Open Custom coding keys and add this code inside the Employee type:

enum CodingKeys: String, CodingKey {
  case name, id, favoriteToy = "gift"
}

CodingKeys is the special enum mentioned above. It conforms to CodingKey and has String raw values. Here’s where you map favoriteToy to gift.

If this enum exists, only the cases present here will be used for encoding and decoding, so even if your property doesn’t require mapping, it has to be included in the enum, as name and id are here.

Run the playground and look at the encoded string value — you’ll see the new field name in use. The JSON doesn’t depend on your stored properties anymore, thanks to custom coding keys.

Time for your next challenge!