【问题标题】:Deserialize a generic object that contains a generic object反序列化包含泛型对象的泛型对象
【发布时间】:2018-08-25 15:01:21
【问题描述】:

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

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

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

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

 ) : BaseVO()

我有一个类可以从 web 服务或数据库或两者中获取数据。当实例化这个类时,我传递了我必须返回的结果类型。从数据库返回的结果与从 Web 服务返回的结果类型不同。当必须从数据库中获取结果时,通过实例化这个类,我传递了一个简单的泛型类型,例如“用户”,但是当必须从 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]}

请帮忙?

【问题讨论】:

    标签: android kotlin gson


    【解决方案1】:

    简答:键入擦除。

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

    幸运的是,Kotlin 有 reified generics

    将您的函数声明更改为:

    inline fun &lt;reified T&gt; convertFromString(data: String?) : T?,一切都会好起来的。

    【讨论】:

    • 嗨,Alexey,感谢您的回答。我已经尝试过这种方法,但它要求使用一个类作为具体类型参数,而不是通用的 'ResultType'。
    • 也许我错过了什么。 ResultType 是什么?它与任何其他类有何不同?
    • 当我实例化这个类时,我有 2 个通用类型:抽象类 DataSourceManager.. ResultType 是通用的,可以是来自本地数据库的数据,也可以是来自 web 服务的响应。
    • 仍然没有发现任何问题。你反序列化了ResultType,而不是DataSourceManager。尝试发布调用convertFromString() 的代码,也许会给出一些线索。
    • 我也搞不懂是什么问题!我写的一切似乎都是合乎逻辑和正确的!我在另一个答案中写了我的代码,你现在可以看到它,谢谢:)
    【解决方案2】:

    实例化DataSourceManager类的方法,我有两个泛型,“List”是webservice查询的参数类型,ApiResponse>是webservice的响应类型。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-15
      • 1970-01-01
      相关资源
      最近更新 更多