Swift 4 has brought with it a ton of great improvements. Today we'll cover one of them, it's the new Codable
protocol! Codable
ships with Swift 4 as part of the Swift standard library and allows us to conform our own types to it to get encoding and decoding functionality "for free".
Encoding and decoding types has never been easier.
Let's dive in!
Before we begin lets back up a second and look at what we're trying to accomplish when it comes to encoding and decoding.
Essentially we want to take an instance of an object or struct and convert (or "encode") it into some other, (usually "machine-readable") format. Then, later, we want to be able to convert (or "decode") the information in that format back into our object or struct.
These days the most common format for encoding/decoding is JSON. It's supported just about everywhere and has the advantage of being both human and machine readable.
For this reason, we'll be discussing JSON in this Bite. It's important to note though, that Codable
isn't specific to just JSON. It's built to support encoding and decoding into just about any format we can think of.
In the past, we might have used something like the JSONSerialization
class in Foundation to do encode our types into JSON.
This works great, but the encoding input and decoding output was either a Dictionary<String: Any>
, or an Array
of them. Then we'd need to manually convert to/from our "real" types.
With Codable
, we can do much better!
Let's start with a simple struct conforming to Codable
:
struct Spaceship : Codable {
var name: String
}
let ship = Spaceship(name: "Skyhopper")
Now, all we need to do to convert our ship
to JSON is:
let data = try? JSONEncoder().encode(ship)
This returns a Data
that we can send to a server, store to disk, or do anything else we need with.
Let's convert it to a string real quick so we can take a look at it:
if let string = String(data: data, encoding: .utf8) {
print(string)
}
This prints:
{"name":"Skyhopper"}
Nice! Notice how we didn't need to specify the names of the "keys" in the JSON, they are inferred from the property names on our struct.
For decoding, we can easily go the other way:
let ship = try? JSONDecoder().decode(Spaceship.self, from: data)
Note how both the .encode
and .decode
functions can throw
and thus we're using the try?
keyword to return a nil
Optional
if encoding or decoding fails.
Before we go let's cover one more nice thing about Codable
.
Let's add another struct to the mix:
struct Person : Codable {
var firstName: String
var lastName: String
}
struct Spaceship : Codable {
var name: String
var pilot: Person
}
Nice. Now when we encode a Spaceship
, the system notices that the pilot
property's value is also Codable
and does the right thing for us automatically:
{"name":"Skyhopper", "pilot":{"firstName":"Luke", "lastName":"Skywalker"}}
That's all for today, next time we'll look at using Codable
with more complex types of data likes Dates
. Happy coding!