Swift Codable Protocol Part I: Why Codable?

Written by: on April 16, 2018

Codable; the data-parsing dream come true!

TLDR;

Data parsing is a necessity in most mobile application development. Theoretically, parsing methods are straightforward and predictable, but in reality they can be complex and prone to bugs. As an application’s scope is inevitably expanded to consume more data, complications and the opportunity for bugs increase exponentially.

Codable is the combined protocol of Swift’s Decodable and Encodable protocols. Together they provide standard methods of decoding data for custom types and encoding data to be saved or transferred. In this article I will explain why we should use Codable in our applications moving forward. If you would like to know more about how to implement it, start with Apple’s overview of Codable, and then check out Part 2 of this article series.

Prior to the introduction of Codable, data decoding required verbose checks for if the desired keys existed and if those values were of the expected type before setting them as property values on a Swift object. Codable, when used with well-formatted JSON, eliminates almost all of the checks that parsing code requires for returning a data object. As data gets more complicated, we can handle the complexity in various stages to keep our code as minimal and clean as possible.

Why should we use it?

Well-written code is efficient, readable, and maintainable. As a general rule, when data gets more complicated, the code to parse that data into a Swift object gets harder to read and maintain.

Decodable provides a template for parsing data with simple, easy-to-understand code. It reuses existing property declarations of a custom type, separates dictionary-key strings into their own enumeration, and eliminates much of the type-safety boilerplate necessary in decoding data.

Below is an example of just how simple Codable can make the data parsing process. Notice that the first object, parsed without Codable, takes about 19 lines of code. The second object, using Codable, takes just 5 lines of code.

Codable eliminates the need for any initializing function, given that we are content with our object’s properties having the same name as their JSON keys, and can assume that the JSON data is in the same format we expect the Object’s properties to be in (i.e. strings properly capitalized, URLs with or without schemes).

If more “Swift-y” property names are desired, we simply add a CodingKeys enum to our Object, mapping them to their respective JSON keys, like so:

In the example above, despite adding the initialization function, we have eliminated the need for many verbose “if-let” and “guard-else” statements while parsing the code (only necessary when handling the optional return from creating a URL). Additionally, notice that the regular, non-optional, id property and the optional caption property are parsed using the same code syntax. The first parameter of the decode function for caption specifies that it expects an optional value by appending a question mark after the expected data type.

At this point, our parsing code is nearing the length of the original non-Codable object. However, the new code is more clear, and separates the areas of the code where typos are commonly made (the strings specifying JSON keys) into an easily identifiable enum.

By separating the JSON keys into an enum and eliminating the need for most “if-let” and “guard-else” statements, the Codable protocol shown above gives us ample room to build upon our objects without drastically increasing the complexity of the code.

Individuals or teams who manage both their back-end and front-end code generally have the freedom to continuously adjust their data model to work with their visual models, with little overhead logistics (if you’ve never been to a meeting between equally stubborn front-end and back-end developers, count yourself lucky). For those that fall into that category, the benefits of implementing Codable are to have Swift objects declared and parsed with the least amount of code possible and to keep up with Apple’s best practices and expectations. However, if you are on a large scale development team dealing with API’s provided by a separate entity, where you cannot control the timing or details of changes in the data you expect to be returned, Codable could be your shining beacon of hope amidst the madness.

Imagine making three API calls in different areas of an application, where each is supposed to return the exact same Swift object. In this unfortunate API, each of those calls happens to return data with a slightly different dictionary key; object_id, obj_id, and Object_ID, all intending to refer to the same property, objectId, on the object you aim to create. Previously, a decoding function would need to have a series of “if-let” statements to check for the id in each of those keys before ultimately deciding which, if any, value to set as the property.

Codable allows you to insert an additional clarifying stage into the process of decoding data into a Swift object. This stage is the “parsed object,” whose properties and keys match up directly to the data, but whose types have been decoded into Swift objects.

In this case, three different parsed objects, each corresponding to a specific API call, could then be used in three different initializers on the single Swift object, which can then be passed around for caching and UI display, without further complicating the code. The separate initializers tied to specific API calls make the reason (a less-than-ideal-API) for the complex code obvious. In the future, if the API were updated to return more concise data, a developer would be able to simply remove the corresponding parsed object, and replace it’s instances with the single correct object.

That intermediary parsed object allows Codable to gracefully handle varying data objects within a single API that are each intended to be parsed into one specific Swift object. It also allows a developer to easily swap between different “parsed objects” created from completely separate API’s, avoiding the need to change the model object that is being used in the rest of the application. By providing different “parsed objects,” there is less code at risk of errors from key mismatching, unexpected types, and unexpected nil values. For a code example of this situation and more like it, visit Part 2 of this article.

Unfortunately, as you introduce more complex and variable data, the Codable benefit of less code will usually be lost; however, the code that you do have will still be more readable than in pre-Codable decoding implementations.

Like any new protocol, it will take a small amount of time to learn the proper Codable syntax. Apple provided a useful short tutorial during WWDC 2017, and in Part 2 of this article we will show some real implementation examples and how to handle common data complexities not shown in Apple’s tutorial. I hope with this short summary, examples, and resources I have linked you will begin parsing data using the Codable protocols, and enjoying the pleasures derived from simple, well-written code.

TLDR;

Pros of Codable:

  • Reduces the lines of code necessary to parse simple data
  • Separates strings indicating JSON keys into an easy-to-read enum
  • Eliminates the need for many if-let and guard-else statements
  • Helps eliminate repetitive models used to deal with less-than-ideal API’s

Cons of Codable:

  • In some complex cases, code length could be the same as without Codable
  • Normal learning curve for implementation

Resources for Implementation:

Melissa Guba

Melissa Guba

Melissa has been developing iOS applications for 4+ years and is currently a Software Developer at POSSIBLE Mobile. She is passionate about writing simple and efficient code for focused user experiences.
Article


Add your voice to the discussion: