Skip to main content

Encoding and decoding data using Codable

About 3 minSwiftArticle(s)bloghackingwithswift.comswiftswift-4.0

Encoding and decoding data using Codable 관련

HACKING WITH SWIFT

What's new in Swift?

Encoding and decoding data using Codable | Changes in Swift 4.0

Encoding and decoding data using Codable

Available from Swift 4.0

We know value types are great, but we also know they interact terribly with Objective-C APIs such as NSCoding – you either need to write a shim layer or give in and use classes, both of which are unpleasant. Worse, even if you give in and switch to classes, you still need to write your encoding and decoding methods by hand, which is painful and error-prone.

Swift 4 introduced a new Codable protocol that lets you serialize and deserialize custom data types without writing any special code – and without having to worry about losing your value types. Even better, you can choose how you want the data to be serialized: you can use classic property list format or even JSON.

Let's take a look at how beautiful this is. First, here's a custom data type and some instances of it:

struct Language: Codable {
    var name: String
    var version: Int
}

let swift = Language(name: "Swift", version: 4)
let php = Language(name: "PHP", version: 7)
let perl = Language(name: "Perl", version: 6)

You can see I've marked the Language struct as conforming to the Codable protocol. With that one tiny addition, we can convert it to a Data representation of JSON like this:

let encoder = JSONEncoder()
if let encoded = try? encoder.encode(swift) {
    // save `encoded` somewhere
}

Swift will automatically encode all properties inside your data type – you don't need to do anything.

Now, if you're like me and have a long history of using NSCoding, you're probably somewhat doubtful: is that really all it takes, and how can we be sure it's working? Well, let's add some more code to try converting the Data object into a string so we can print it out, then decode it back into a new Language instance that we can read from:

if let encoded = try? encoder.encode(swift) {
    if let json = String(data: encoded, encoding: .utf8) {
        print(json)
    }

    let decoder = JSONDecoder()
    if let decoded = try? decoder.decode(Language.self, from: encoded) {
        print(decoded.name)
    }
}

Notice how decoding doesn't require a typecast – you provide the data type name as its first parameter, so Swift infers the return type from there.

Both JSONEncoder and its property list counterpart PropertyListEncoder have lots of options for customizing how they work: do you want compact JSON or pretty-printed JSON? Do you want to use ISO8601 dates or Unix epoch dates? Do you want to use binary property lists or XML? For more information on these and other options, see the Swift Evolution proposal for this new feature (apple/swift-evolution)open in new window.

Other Changes in Swift 4.0
Multi-line string literals | Changes in Swift 4.0

Multi-line string literals
Improved keypaths for key-value coding | Changes in Swift 4.0

Improved keypaths for key-value coding
Improved dictionary functionality | Changes in Swift 4.0

Improved dictionary functionality
Strings are collections again | Changes in Swift 4.0

Strings are collections again
One-sided ranges | Changes in Swift 4.0

One-sided ranges

Download Swift 4.0 playgroundopen in new window


이찬희 (MarkiiimarK)
Never Stop Learning.