Kotlin

Sealed Classes Serialization And Deserialization with Kotlinx Serialization Library

Google+ Pinterest LinkedIn Tumblr

Kotlin getting more popular day-by-day for its conscience and higher productivity. Even more than 67% of Android developers who use the Kotlin language say it has increased their productivity. While working with kotlin we often need to use the sealed classes and in order to serialize and deserialize the sealed class, we can easily use the Kotlinx Serialization library.

So, in this article, I’ll walk through you how to serialize and deserialize the sealed classes using the Kotlinx Serialization library.

To find out the basics of Kotlinx Serialization check out the following article.

Gradle Stuff

Kotlinx Serialization requires us to add some more stuff to our application module build.gradle file. We start by adding the following dependencies.

apply plugin: 'kotlinx-serialization'   // kotlin serialization plugin

 dependencies {   
    // Kotlinx Serialization
    implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0"
}

We also need to add a classpath for the Kotlinx Serialization library inside the top-level build.gradle file buildScript->dependencies section.

buildscript {
    ext.kotlin_version = '1.4.30'
    repositories {
        google()
        jcenter()
    }
    dependencies {
        ......
        classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
    }
}

Structure of sealed class

The structure of our sealed class is pretty simple. I have one top-level sealed class and inside that class, there are several inheritance hierarchies. First, let’s see the structure.

@Serializable
sealed class AnsweredContent {

    @Serializable
    data class SingleTextContent(val answer: String) : AnsweredContent()

    @Serializable
    data class MultiChoiceContent(val choices: List<String>) : AnsweredContent()

    @Serializable
    data class LocationContent(val latitude: Double, val longitude: Double, val accuracy: Float) : AnsweredContent()
}

One thing we need to make sure that all sub-classes and top-level sealed classes must be explicitly marked with @Serializable annotation.

Serialization of Sealed ClasseS

Now it’s time to see the magic of the Kotlinx Serialization library.

// Serialization of sealed classes
val multiChoiceContent: AnsweredContent = AnsweredContent.MultiChoiceContent(listOf("Jack", "Jill"))
    val locationContent: AnsweredContent = AnsweredContent.LocationContent(34.221212, 70.2121212, 15f)
    val multiChoiceSerialization = Json.encodeToString(AnsweredContent.serializer(), multiChoiceContent)
    val locationContentSerialization = Json.encodeToString(AnsweredContent.serializer(), locationContent)
    println(multiChoiceSerialization)
    println(deserializeLocationContent)

// The output of above sealed classes serialization
{"type":"AnsweredContent.MultiChoiceContent","choices":["Jack","Jill"]}
{"type":"AnsweredContent.LocationContent","latitude":34.221212,"longitude":70.2121212,"accuracy":15.0}

This the most straightforward way to serialize the sealed classes by calling Json.encodeToString. In the output along with other properties, we have the type key added to the resulting JSON object as a discriminator.

Deserialization of Sealed Classes

To deserialize a sealed class instance from JSON string we need to use the Json.decodeFromString method that exists in the Kotlinx Serialization library.

val deserializeMultiChoiceContent = json.decodeFromString(AnsweredContent.serializer(), multiChoiceSerialization)
    val deserializeLocationContent = json.decodeFromString(AnsweredContent.serializer(), locationContentSerialization)
    println(deserializeMultiChoiceContent)
    println(deserializeLocationContent)

// Output of above sealed classes deserialization
MultiChoiceContent(choices=[Jack, Jill])
LocationContent(latitude=34.221212, longitude=70.2121212, accuracy=15.0)

To specify which type we want as a result of deserialization we need to pass the serializer for that in the decodeFromString method. And another parameter we need to pass is the JSON string.

List of Sealed Classes Serialization & Deserialization

Let’s say we need to parse the list of sealed classes instead of a single instance of the sealed class.

val multiChoiceContent: AnsweredContent = AnsweredContent.MultiChoiceContent(listOf("Jack", "Jill"))
    val locationContent: AnsweredContent = AnsweredContent.LocationContent(34.221212, 70.2121212, 15f)
    val answeredContentsSerialization =
        Json.encodeToString(ListSerializer(AnsweredContent.serializer()), listOf(multiChoiceContent, locationContent))
    print(answeredContentsSerialization)

Two things that are changed from the previous serialization code. These are:

  1. In the encodeToString method, we pass the ListSerializer. The ListSerializer creates a serializer for the given type and for our case the type related to AnsweredContent.
  2. Another param we need to pass is the list of AnsweredContent instances.

Now let us see how we can deserialize the list of the sealed classes JSON string into a list of instances.

val answeredContents =
        Json.decodeFromString(ListSerializer(AnsweredContent.serializer()), answeredContentsSerialization)
    print(answeredContents)

Same as before just one change we need to pass the ListSerializer of AnsweredContent type instead of single KSerializer.

Alright, guys, this was my understanding of how to serialize and deserialize the sealed classes through the Kotlinx Serialization library. If you any queries or suggestions on improving the above example please let me know in the comments section.

Thank you for being here and keep reading…

2 Comments

    • ahsensaeed067 Reply

      Hey faith,
      When I wrote this post using the 0.11.0 version this is the best solution I came up with in order to serialize & deserialize the sealed classes. I’ll update my article according to the newly released version.

      Also, good to hear that in the future the library will be capable of serializing sealed classes internally.

Write A Comment