GSON Десериализация подтипов в Котлине - PullRequest
1 голос
/ 27 сентября 2019

Я не уверен, является ли это ограничением, ошибкой или просто неправильным использованием GSON.Мне нужно иметь иерархию объектов Kotlin (родитель с различными подтипами), и мне нужно десериализовать их с помощью GSON.Десериализованный объект имеет правильный подтип , но его поле enumField фактически равно нулю .

Сначала я подумал, что это потому, что поле передается конструктору "super", но потом я обнаружил, что "super" хорошо работает для строки, просто enum не работает.

См. Этот пример:

import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.typeadapters.RuntimeTypeAdapterFactory

open class Parent(val stringField: String,
                  val enumField: EnumField) {

    enum class EnumField {
        SUBTYPE1,
        SUBTYPE2,
        SUBTYPE3
    }
}


class Subtype1() : Parent("s1", EnumField.SUBTYPE1)
class Subtype2(stringField: String) : Parent(stringField, EnumField.SUBTYPE2)
class Subtype3(stringField: String, type: EnumField) : Parent(stringField, type)

val subtypeRAF = RuntimeTypeAdapterFactory.of(Parent::class.java, "enumField")
        .registerSubtype(Subtype1::class.java, Parent.EnumField.SUBTYPE1.name)
        .registerSubtype(Subtype2::class.java, Parent.EnumField.SUBTYPE2.name)
        .registerSubtype(Subtype3::class.java, Parent.EnumField.SUBTYPE3.name)

fun main() {
    val gson = GsonBuilder()
            .registerTypeAdapterFactory(subtypeRAF)
            .create()

    serializeAndDeserialize(gson, Subtype1()) // this works (but not suitable)
    serializeAndDeserialize(gson, Subtype2("s2")) // broken
    serializeAndDeserialize(gson, Subtype3("s3", Parent.EnumField.SUBTYPE3)) // broken
}

private fun serializeAndDeserialize(gson: Gson, obj: Parent) {
    println("-----------------------------------------")
    val json = gson.toJson(obj)
    println(json)
    val obj = gson.fromJson(json, Parent::class.java)
    println("stringField=${obj.stringField}, enumField=${obj.enumField}")
}

Есть идеи, как добиться десериализации enumField?

1 Ответ

0 голосов
/ 27 сентября 2019

Попробуйте добавить @SerializedName аннотацию к каждому перечислению.

enum class EnumField {
    @SerializedName("subtype1")
    SUBTYPE1,
    @SerializedName("subtype2")
    SUBTYPE2,
    @SerializedName("subtype3")
    SUBTYPE3
}
...