Десериализовать универсальный объект, который содержит универсальный объект - PullRequest
0 голосов
/ 25 августа 2018

У меня проблема в том, что я не нашел, как ее решить.У меня есть этот класс, который «данные» является общим объектом

class ApiResponse <DataType>
 (
      @SerializedName("requestType")
      val type : RequestTypeEnum,

      @SerializedName("requestState")
      val state : RequestStateEnum,

      @SerializedName("requestAI")
      val data : DataType?

 ) : BaseVO()

, и у меня есть класс, который извлекает данные из веб-службы или из базы данных, или и то, и другое. При создании экземпляра этого класса я передаю типрезультата, который я должен вернуть.Результат, возвращаемый из базы данных, не имеет тот же тип, что и результат, возвращаемый из веб-службы.Когда результат должен быть получен из базы данных, при создании экземпляра этого класса я передаю простой универсальный тип, который может быть, например, «Пользователь», но когда результат должен быть получен из веб-службы, я должен создать экземпляр этого класса с универсальным типом.«ApiResponse», который также содержит объект универсального типа.

Это мой класс:

abstract class DataSourceManager<ParamsType , ResultType>

, и вот как я его создал

return object : DataSourceManager<List<String> , ApiResponse<List<String>>>()
{...}.asLiveData

, когда я отображаю вВ журнале результат как String отображает корректно

{
  "requestType": "WEB_SOCKET_TEST_SPONSOR_CODE",
  "requestState": "ERROR",
  "requestAI": [
    "ERROR_MISSING_INFORMATIONS"
  ]
}

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

вот моя попытка десериализации

val apiResponse = convertFromString<ResultType>(pApiResponseAsString)
.
.
.

 fun <T> convertFromString(pDataAsString : String?) : T?
 {
      val dataType : Type = object : TypeToken<T>(){}.type
      return Gson().fromJson<T>(pDataAsString , dataType)
 }

, когда я пытаюсь обработать результат как преобразованный объект, я получаю ошибку:

java.lang.ClassCastException: libcore.reflect.TypeVariableImpl cannot be cast to com.PackageName.ApiResponse

Но когда я отображаюрезультат в журнале, он находит этот формат недействительным:

{requestType=WEB_SOCKET_TEST_SPONSOR_CODE, requestState=ERROR, requestAI=[ERROR_MISSING_INFORMATIONS]}

Некоторая помощь, пожалуйста?

Ответы [ 2 ]

0 голосов
/ 26 августа 2018

метод, который создает экземпляр класса DataSourceManager. У меня есть два универсальных типа: «List » - это тип параметра запроса веб-службы, а ApiResponse > - это тип ответа веб-службы.

fun verifyReferralCode(pReferralCode : String) : LiveData<ApiResponse<List<RequestStateEnum>>>
     {
          return object : DataSourceManager<List<String> , ApiResponse<List<RequestStateEnum>>>()
          {
               override fun createWebserviceCall() : ApiRequest<List<String>>
               {
                    return ApiRequest(RequestTypeEnum.VERIFY_REFERRAL_CODE , listOf(pReferralCode))
               }

               override fun sessionToken() : String?
               {
                    return null
               }

               override fun operationCompleted(params : List<String>? , result : ApiResponse<List<RequestStateEnum>>)
               {}

          }.asLiveData
     }

Это объект ApiResponse

class ApiResponse<DataType>
 (
      @SerializedName("requestType")
      val type : RequestTypeEnum,

      @SerializedName("requestState")
      val state : RequestStateEnum,

      @SerializedName("requestAI")
      val data : DataType

 ) : BaseVO()

Это класс DataSourceManager, он не завершен, но содержит необходимый код, который мне нужен сейчас.

abstract class DataSourceManager<ParamsType , ResultType>
{
 @MainThread
 abstract fun createWebserviceCall() : ApiRequest<ParamsType>

 @MainThread
 abstract fun sessionToken() : String?

 @WorkerThread
 abstract fun operationCompleted(params : ParamsType? , result : ResultType)


 private val resultLD = MediatorLiveData<ResultType>()
 val asLiveData : LiveData<ResultType> get() = resultLD


 init
 {
      performWebRequest()
 }


 private fun performWebRequest()
 {
      val request = createWebserviceCall()

      val webserviceSource = WebSocketWS.executeRequest(request.requestType , request.toString())

      resultLD.addSource(webserviceSource) {pApiResponseString ->

           resultLD.removeSource(webserviceSource)

           //pApiResponseString is String which contains a valid Json object.
           val apiResponse = convertFromString<ResultType>(pApiResponseString )

           //resultLD.postValue(apiResponse)
           //saveResultToCache(request.requestAI, apiResponse!!)
      }
 }


 private fun <T> convertFromString(pDataAsString: String?) : T?
 {
      val dataType = object : TypeToken<T>(){}.type

      return Gson().fromJson(pDataAsString, dataType)
 }


 @MainThread
 private fun saveResultToCache(params : ParamsType? , result : ResultType)
 {
      Execution.instance.databaseIO.execute {

           operationCompleted(params, result)
      }
 }
}
0 голосов
/ 25 августа 2018

Краткий ответ: тип стирания.

Когда вы делаете fun <T> convertFromString(data: String) : T и пытаетесь получить тип данных: val dataType : Type = object : TypeToken<T>(){}.type ваш тип будет Object

К счастью для нас, Kotlin имеет усовершенствованные генерики .

Измените объявление функции на:

inline fun <reified T> convertFromString(data: String?) : T?, и все будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...