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ă.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Encoding and Decoding in Swift
25 mins
- Getting Started
- Encoding and Decoding Nested Types
- Switching Between Snake Case and Camel Case Formats
- Working With Custom JSON Keys
- Working With Flat JSON Hierarchies
- Working With Deep JSON Hierarchies
- Encoding and Decoding Dates
- Encoding and Decoding Subclasses
- Handling Arrays With Mixed Types
- Working With Arrays
- Working With Arrays Within Objects
- Where to Go From Here?
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.
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.
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! :]
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.
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:
- Encode
employee
to JSON withencode(_:)
(I told you it was easy!). - Create a string from the encoded
data
to visualize it.
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! :]
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!