3

I have a field that I want to deserialize into an instance of a sealed subclass based on a value on that Json object.

[
  {
    "id": 1L,
    "some_array": [],
    "my_thing": {
      "type": "sealed_subclass_one",
      "other_thing": {
        "thing": "thing is a string"
      }
    }
  }, {
    "id": 2L,
    "some_array": [],
    "my_thing": {
      "type": "sealed_subclass_two",
      "other_thing": {
        "other_thing": "other_thing is a string too"
      }
    }
  },
]

Response model:

@Serializable
data class MyResponse(
  @SerialName("id") 
  val id: Long

  @SerialName("some_array") 
  val someArray: Array<Something>

  @SerialName("my_thing") 
  val myThing: MySealedClassResponse
)

MySealedClass

@Serializable
sealed class MySealedClassResponse : Parcelable {
    @Serializable
    @SerialName("type")
    data class SealedSubclassOne(
        val thing: String
    ) : MySealedClassResponse()

    @Serializable
    @SerialName("type")
    data class SealedSubclassTwo(
        val otherThing: String
    ) : MySealedClassResponse()
}

As it stands, I'm getting a serialization exception because the serializer doesn't know what to do :

kotlinx.serialization.SerializationException: sealed_subclass_one is not registered for polymorphic serialization in the scope of class com.myapp.MyResponse

Is there an easy way to register the values of type so that deserialization can happen without a custom serializer?

Tyler
  • 19,113
  • 19
  • 94
  • 151

1 Answers1

3

I believe if you change @SerialName("type") to @SerialName("sealed_subclass_one") (and likewise for the SealedSubclassTwo declaration) it should be able to find the correct serializer.

The SerialName attribute on the sealed sub-type is what it looks to in order to associate the json's type attribute with the appropriate sub-class (and thus the appropriate serializer instance).

See https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/polymorphism.md#a-bit-of-customizing for more details. But the germane portion of that doc is:

By default, encoded type name is equal to class' fully-qualified name. To change that, you can annotate the class with @SerialName annotation

jbraun
  • 68
  • 1
  • 7