Decodable with dynamic keys in Swift

Grzegorz Przybyła
ITNEXT
Published in
2 min readAug 26, 2019

--

Decodable and Encodable protocols are my very favourite feature since Swift 4.0. You can check my first article about Codable enum in Swift here: https://blog.untitledkingdom.com/codable-enums-in-swift-3ab3dacf30ce?gi=4c150f2a90ff. In this article, I would like to present how to, in a very handy way, handle JSON responses with dynamic keys inside.

The case

In our application we need to handle the user JSON representation, which can be sent in two different ways:

{"name": "Jon","surname": "Doe","age": 42,"isAdmin": true}

or

{"name": "Jan","surname": "Kowalski","age": 42,"isViewer": true}

It can be some legacy API contract, it can be some response form third part device like BLE device, or maybe just some String’ish way to communicate, anyway, we need to handle it, and we need to know the role of given user.

Let’s start with defining UserModel

JSONSerialization-way:

It’s more like Obj-C code where we start from parsing JSON string object into Swift Dictionary (of type [String: Any]), and then dynamically basing on values inside the dictionary we are extracting proper role and all other properties, like name and age. Of course, it will work, but it has some drawback.

Pros:

  • Easy to read and understand
  • Easy to implement

Cons:

  • Poorly reuseable
  • Not fittable for generic solution (Codable, Mapping)

Decodable for the rescue!

Here we are extracting all the keys into DynamicKey object, and then we are matching through all keys in container looking for “isAdmin” or “isViewer” key. If we found given key, we need to check Bool value for this key, and then we can store proper user role.

For all other keys, we are using traditional CodingKey enum codable solution.

DynamicKey implementation should look like:

Pros:

  • Generic and reusable (Decodable)
  • Encodable can be easily adopted
  • You can use different serialisation types (JSON, XML)

Cons:

  • Harder to read and understand

Conclusions:

In this article once again we can see that Decodable (and Encodable) protocols are more powerful than we can even think. Sometimes it’s worth to consider to implement `init(from: decoder)` implementation instead of taking mapping or JSONSerialization path.

So happy code! 🚀

--

--