Do you use Codable protocol often? Here is a clean trick!
Say goodbye to unnecessary optionals and complex decoding logic
Have you ever encountered the challenge of handling JSON responses? Often, we find ourselves making trade-offs by making properties nullable or introducing unwanted changes in the model just to facilitate decoding.
We are left with properties we don't actually need, and every modification introduces the risk of impacting other modules (unless we have comprehensive tests in place).
Let’s consider an example to illustrate this problem. Imagine that we need to display a list of books, with each book showing the title, author, and publication year. To achieve this, we have two JSON endpoints: Authors and Books.
Authors JSON
Books JSON
Given the structure and requirements, we are prompted to design the following structure:
As you can see, we make the author
property optional and mutable just for the decoder. Later, we replace the author
from nil
to the actual author name mapped from the author response. However, this leads to optional handling in the presentation layer, which is not related to the UI.
What is the proposed solution for this problem?
Let’s introduce a BookItemMapper
. The responsibility of this mapper is to handle the data in an encapsulated way, providing an array of [Book]
or an error if it fails to do so.
Let’s see it in action.
The BookItemMapper
takes care of all the decoding and correctly maps the author in each Book
object. It returns a simple model that can be safely used in our presentation layer.
Noticed how the Root
and Item
model conforming to Decodable are private? They are only used for decoding and meeting the exact requirements of the Decoder.
Also, we get the control of handling the result however we need, in our case simply mapping it to array of Book
With the introduction of the BookItemMapper
, we can now simplify our BookItemLoader
Resulting in no unnecessary nullable, no mutating, just pure model. You can now use the BookItemLoader
in your presentation module and implement the UI without worrying about the complexities of the handling the data.
The BookItemLoader
now relies on the BookItemMapper
to handle the data mapping. It provides a completion handler that returns either an array of books or an error, based on the result.
By leveraging the power of the Codable protocol and introducing a dedicated mapper, we gain more control over the decoding process while keeping our models pure and focused. This approach not only improves the readability and understandability of our codebase but also reduces the risk of introducing bugs when making modifications. Overall, it’s a clean and efficient solution that enhances the overall development
Additionally, consider using the DispatchQueueDecorator to further improve your code and simplify the UI level without worrying about threading logic.
Start implementing this already! If you have any further questions or need additional assistance, feel free to ask.