Even More About Swift’s Codable
Ben Scheirman (via Kuba Suder):
Instead, we can use a special method to get a super-class ready encoder that already has a container attached to it[…]
[…]
Here we have a
migration_datefield that has a different date format than thecreated_atfield. Let’s also assume that the name property has since been changed to justname.This is obviously not an ideal situation, but real-life happens and sometimes you inherit a messy API.
[…]
This is a listing of beer styles, but the keys are actually the name of the style. We could not represent every possible case with an enum as it could change or grow over time.
Instead, we can create a more dynamic implementation of
CodingKeyfor this.
This is the most comprehensive guide to Codable and JSON that I’ve seen.
The new
Codableprotocol is flexible enough to allow a different encoded representation from the in-memory representation which is a nice property to have in a serialization mechanism. Today I’m going to buildSingleValueCodableto automate that work when dealing withRawRepresentabletypes.
So
Dictionaryseems to behave differently depending on itsKeytype, even though the enum values are ultimately encoded as strings. What’s going on here? We can find the answer inDictionary’s implementation for theEncodableprotocol.[…]
There are three branches: only if the dictionary’s key type is
StringorIntdoes it use a keyed container. Any other key type triggers results in an unkeyed container of alternating keys and values.
SE-0167 introduced
Codableconformance for some types in the standard library, but not theRangefamily of types. This proposal adds that conformance.
There’s quite an interesting discussion about this, because the details of how it works will end up affecting databases and APIs outside of Swift itself.
The two key takeaways here are
If you need to represent a collection that can have multiple types then you’ll need some form of wrapper and
enums can perform that duty well when it makes sense.Swift’s
Codableis really powerful and helped remove a heap of issues that arise from manually parsing/creating objects.Removing optionality, reifying types and using compiler generated code are great ways of simplifying our code. In some cases this also helps move runtime crashes into compile time issues, which is generally making our code safer. The benefits here are great and it shows that it’s really worth taking time to model your data correctly and then use tools like
Codableto munge between representations.
Testing
Codableimplementations isn’t particularly hard but the boilerplate code required can get out of hand pretty quickly. I thought I’d run through a TDD process to get to the final solution as I find this stuff personally interesting and hopefully someone else might to. Hopefully I’ve highlighted some basic stuff to test when looking at customDecodableimplementations and shown that it’s useful to refactor not only the production code but the test code as well.
The challenge I see is how to make sure that you don’t break compatibility as you evolve your data model.
Update (2019-01-24): itaiferber:
Hello, everyone! As part of the review thread for SE-0239, we received a lot of helpful feedback that’s highlighted areas where we thing Codable can improve, and we wanted to take the time after the holidays to split that conversation aside and help carry it along in a more targeted thread. We think there are a lot of potential improvements to be made, and we’re really interested in getting community feedback and contributions to help us get closer to where we’ve always wanted Codable to be.