WWDC24 SALE: Save 50% on all my Swift books and bundles! >>

Swift 4.1 improves Codable with keyDecodingStrategy

Snake case is now just a few keystrokes away.

Paul Hudson       @twostraws

Swift 4.0 brought many great new features, including multi-line strings, better keypaths, and lots of improved dictionary functionality. But it also gave us Codable for the first time: by far the easiest, safest way to convert Swift objects into JSON and XML.

However, Codable had one particular annoyance that hit most users: if your JSON used snake_case for its key names and your Swift code used camelCase for its property names, Codable wouldn’t be able to convert between the two – you needed to create your own CodingKeys mapping to explain how the two matched up.

Well, Swift 4.1 has fixed this beautifully: along with awesome new features of its own there’s a new keyDecodingStrategy property on JSONDecoder that can automatically convert between snake_case and camelCase if you need it. The inverse property, keyEncodingStrategy, also exists on JSONEncoder so you can convert your Swift camelCase names back into snake_case.

Enough chat – let’s look at a practical example. Create a new Playground and give it this JSON string:

let jsonString = """
[
    {
        "name": "MacBook Pro",
        "screen_size": 15,
        "cpu_count": 4
    },
    {
        "name": "iMac Pro",
        "screen_size": 27,
        "cpu_count": 18
    }
]
"""

let jsonData = Data(jsonString.utf8)

That stores an array of two items, each describing a Mac. As you can see, both screen_size and cpu_count use snake case – words are all lowercased, with underscores separating them. I’ve added a conversion to Data at the end, because that’s what JSONDecoder works with.

Now, we want to convert that JSON into an array of Mac instances using this struct:

struct Mac: Codable {
    var name: String
    var screenSize: Int
    var cpuCount: Int
}

That follows standard Swift naming conventions, so the property names are all camelCased – words have no separators, but second and subsequent words all start with a capital letter.

In Swift 4.0 you might try to decode that JSON like this:

let decoder = JSONDecoder()

do {
    let macs = try decoder.decode([Mac].self, from: jsonData)
    print(macs)
} catch {
    print(error.localizedDescription)
}

However, that code won’t work because Codable doesn’t know how to map camelCase keys to the snake_case. This is where the new keyDecodingStrategy property comes in: it’s set to .useDefaultKeys by default, which does a direct mapping of JSON names to Swift properties. However, if you change it to .convertFromSnakeCase then the above code works immediately because Codable handles the name conversion for us.

So, add this line just before the start of the do block:

decoder.keyDecodingStrategy = .convertFromSnakeCase

When you want to go back the other way – to convert a Codable struct with camelCase properties back to JSON with snake_case keys, set the keyEncodingStrategy to .convertToSnakeCase like this:

let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let encoded = try encoder.encode(macs)

If you have more advanced uses – perhaps you prefer SCREAMING_SNAKE_CASE for some reason? – you can also specify a custom key strategy, but looking at the tests for that it seems a rather involved thing to do, at least for now.

For more on the new features in Swift 4.1, see our article what's new in Swift 4.1.

Save 50% in my WWDC sale.

SAVE 50% To celebrate WWDC24, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

BUY OUR BOOKS
Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

Average rating: 4.6/5

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.