Десериализация в запечатанный подкласс на основе значения поля

У меня есть поле, которое я хочу десериализовать в экземпляр запечатанного подкласса на основе значения этого объекта Json.

[
  {
    "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"
      }
    }
  },
]

Модель ответа:

@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()
}

В настоящее время я получаю исключение сериализации, потому что сериализатор не знает, что делать:

kotlinx.serialization.SerializationException: sealed_subclass_one не зарегистрирован для полиморфной сериализации в области действия класса com.myapp.MyResponse

Есть ли простой способ зарегистрировать значения type так что десериализация может происходить без специального сериализатора?

1 ответ

Решение

Я верю, если ты изменишься @SerialName("type") к @SerialName("sealed_subclass_one") (и то же самое для SealedSubclassTwo декларацию) он должен найти правильный сериализатор.

В SerialName Атрибут запечатанного подтипа - это то, на что он смотрит, чтобы связать json type атрибут с соответствующим подклассом (и, следовательно, с соответствующим экземпляром сериализатора).

См. https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/polymorphism.md для получения дополнительных сведений. Но основная часть этого документа:

По умолчанию имя закодированного типа равно полному имени класса. Чтобы изменить это, вы можете аннотировать класс аннотацией @SerialName.

Другие вопросы по тегам