JSON serialization and generics in Kotlin.
Preface
Sometimes when developing an app, you need to introduce some complexity in order to keep your code neat and clean.
Applying this idea to a bicycle, an internal-gear hub part comes to my mind: the interaction with it is simple and makes life easier if you stop-and-go when commuting in a big city. On the other hand, it is a complex and expensive component.
Curiously, the same example can be found inside Fidesmo app codebase:
The easy interaction
We use a version of the Either<A,B> pattern redefined as Result<T,E>. Popular in languages like Scala, Elm or Rust, it is fantastic because it wraps a value of type T inside a “request context”, where E is the error obtained if the request fails. Although you can find many implementations around, let’s type a simple one:
The complex part
As we are using a Redux like architecture inside Fidesmo app, the Result<A,B> is part of our state and it must be serialized!! 😱
How to serialize a sealed class with generics? In theory, we should add a custom adapter to the Google Gson lib that let’s us customize the JSON (de)codification. This adapter could have the follow structure:
Result<T, E> detection
In order to pass the previous serializer to the Gson implementation, we need something that detects the whole hierarchy of our sealed class: Result.Loading, Result.Ok<T> or Result.Err<E>.
And voilá, The registerTypeHierarchyAdapter
comes to help us:
Result<T, E> serialization
About codification, we have predefined that we’ll save only the Ok
result and discard the other states. A pattern matching can help us to execute the correct action for each case:
Result<T, E> deserialization
Ok, fasten your seat-belts:
Conclusions
Making an application (or software in general) is a matter of decisions, most of them are not transcendental but seen together as a whole can lead your code to a land of pleasure full of unicorns or to terrible hell.
In our case, the introduction of a complex module in benefit of the overall simplicity is a good one though :)