Список десериализации полиморфизма GSON <BaseClass>не отображается на подкласс, если вложен - PullRequest
0 голосов
/ 29 ноября 2018

Я написал JsonDeserializer для сопоставления с подклассами, прочитав тип подкласса из json.Это прекрасно работает, за исключением случаев, когда тип является вложенным, когда тип BaseClass содержит BaseClass.Когда это происходит, десериализатор никогда не вызывается для вложенного класса.Я подал отчет об ошибке , но хочу подтвердить, что это действительно ошибка, или посмотреть, есть ли способ обойти эту проблему.

Полный пример прилагается.Gson версия 2.8.5.Котлин версия 1.3.10

import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonParseException
import java.lang.reflect.Type


open class BaseClass {
    var myType: String? = null
    var myList = mutableListOf<BaseClass>()
    var dep: BaseClass? = null
}

open class ClassA : BaseClass() {
    val astuff: String? = null
}

open class ClassB : BaseClass() {
    val bstuff: String? = null
}

open class Resources {
    val myList = mutableListOf<BaseClass>()
}


val json1 = """
{
  "myList": [
    {
      "myType": "ClassA",
      "astuff": "a stuff"
    },
    {
      "myType" : "ClassB",
      "bstuff" : "things b needs"
    }
  ]
}
""".trimIndent()

val json2 = """
          {
            "myType" : "ClassA",
            "astuff" : "a stuff",
            "myList" : [
              {
                "myType" : "ClassB",
                "bstuff" : "things b needs"
              }
            ]
          }
""".trimIndent()

val json3 = """
          {
            "myType" : "ClassA",
            "astuff" : "a stuff",
            "dep" :               {
                "myType" : "ClassB",
                "bstuff" : "things b needs"
              },
            "myList" : [
              {
                "myType" : "ClassB",
                "bstuff" : "things b needs"
              }
            ]
          }
""".trimIndent()


fun main(args: Array<String>) {

    val gson = getGson()

    // working example
    val test1 = gson.fromJson(json1, Resources::class.java)
    if (!(test1.myList[0] is ClassA)) {
        println("Test1 Error: first array entry should be ClassA but is ${test1.myList[0]::class.java}")
    }

    if (!(test1.myList[1] is ClassB)) {
        println("Test1 Error: first array entry should be ClassB but is ${test1.myList[1]::class.java}")
    }

    // broken examples
    val test2 = gson.fromJson(json2, BaseClass::class.java)
    if (!(test2.myList[0] is ClassA)) {
        println("Test3 Error: first array entry should be ClassA but is ${test2.myList[0]::class.java}")
    }

    val test3 = gson.fromJson(json3, BaseClass::class.java)

}

fun getGson(): Gson {
    return GsonBuilder()
            .registerTypeAdapter(BaseClass::class.java, ClassDeserializerAdapter1<BaseClass>("myType"))
            .create()
}

class ClassDeserializerAdapter1<T> internal constructor(private val typeName: String) : JsonDeserializer<T> {
    private val gson: Gson

    init {
        gson = GsonBuilder()
                .create()
    }

    @Throws(JsonParseException::class)
    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): T {
        val jsonObject = json.asJsonObject
        val typeElement = jsonObject.get(typeName)
        val method = typeElement.asString
        val classType = Class.forName("com.juicelabs.fhir.base.$method") as Class<out T>
        return gson.fromJson(json, classType)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...