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 :)