Как десериализовать ответ JSON в GSON для противоречивого ответа API? - PullRequest
0 голосов
/ 04 мая 2020

Я изучил эту проблему и попытался реализовать то, что смог найти с помощью SO, но безуспешно. Такова моя проблема:

Иногда в моем ответе JSON я получаю поле data как JSON object и другие времена поле данных как JSON array. Технически это плохой дизайн API, однако изменение API на данном этапе неосуществимо.

Два типа JSON ответов по API

{
  data: {
  .
  .
  .
  }
}

{
  data : [
  .
  .
  .
  ]
}

Я пытался реализовать DataDeserializer, однако GSON по-прежнему идентифицирует JSON response как JSON object и не может использовать DataDeserializer:

Класс DataDeserializer

class DataDeserializer : JsonDeserializer<List<Data<Any>>> {
  override fun deserialize(
    json: JsonElement,
    typeOfT: Type?,
    context: JsonDeserializationContext
  ): List<Data<Any>> {
    val dataList = ArrayList<Data<Any>>()

    when {
      json.isJsonObject -> {
        val data = context.deserialize<Data<Any>>(json.asJsonObject, Data::class.java)
        dataList.add(data)
      }
      json.isJsonArray -> {
        for (jsonObject in json.asJsonArray)
          dataList.add(context.deserialize(jsonObject, Data::class.java))
      }
      else -> throw RuntimeException("Unexpected JSON Type: ${json.javaClass}")
    }

    return dataList
  }
}

Классы моделей

open class Json<T> {
  lateinit var data: List<Data<T>>

  fun getFirstChild() = data.first()
}

data class Data<T>(
  private val id: String = "",
  private val type: String = "",
  val attributes: T
)

Регистрация DataDeserializer с помощью GSONConverterFactory

  val gson = GsonBuilder().registerTypeAdapter(Data::class.java, DataDeserializer()).create()
...