反序列化包含通用对象的通用对象

时间:2018-08-25 15:01:21

标签: android kotlin gson

我有一个问题,我没有找到解决方法。 我有一个此类,“数据”是一个通用对象

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

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

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

 ) : BaseVO()

,并且我有一个从Web服务或数据库中或从两者中获取数据的类。实例化此类时,我传递了必须返回的结果类型。从数据库返回的结果与从Web服务返回的结果的类型不同。当必须从数据库获取结果时,通过实例化此类,我传递了一个简单的泛型类型,例如可以是“ User”,但是当必须从Web服务获取结果时,我必须使用泛型类型实例化此类“ ApiResponse”还包含一个通用类型对象。

这是我的课程:

abstract class DataSourceManager<ParamsType , ResultType>

这是我实例化的方式

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

当我在日志中以字符串形式显示结果时,它会正确显示

{
  "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 :(得分:1)

简短答案:键入擦除。

当您执行fun <T> convertFromString(data: String) : T并尝试获取数据类型时:val dataType : Type = object : TypeToken<T>(){}.type您的类型将是Object

幸运的是,科特琳有reified generics

将函数声明更改为:

inline fun <reified T> convertFromString(data: String?) : T?,一切都会正常。

答案 1 :(得分:0)

实例化DataSourceManager类的方法,我有两种通用类型,“ List ”是Web服务查询的参数类型,而ApiResponse >是Web服务的响应类型。

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)
      }
 }
}