Десериализация в запечатанный подкласс на основе значения поля - PullRequest
2 голосов
/ 15 января 2020

У меня есть поле, которое я хочу десериализовать в экземпляр запечатанного подкласса на основе значения этого 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 не зарегистрирован для polymorphi c сериализация в области класса com.myapp.MyResponse

Существует ли простой способ регистрации значений type, чтобы десериализация могла происходить без специального сериализатора?

1 Ответ

2 голосов
/ 20 марта 2020

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

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

См. https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/polymorphism.md#a - немного настройки для более подробной информации. Но немецкая часть этого do c имеет вид:

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

...