首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Kotlin Gson反序列化

Kotlin Gson反序列化
EN

Stack Overflow用户
提问于 2017-12-22 16:41:33
回答 3查看 13.6K关注 0票数 9

我正在接收一个具有映射包装表的JSON数据模型。我试图使用泛型传递超出包装器的类型,但它在运行时翻译得不太好。下面是我的JSON文件的一个示例:

代码语言:javascript
复制
{
"Table": [
 {
   "paymentmethod_id": 1,
   "paymentmethod_description": "Cash",
   "paymentmethod_code": "Cash",
   "paymentmethod_is_ach_onfile": false,
   "paymentmethod_is_element": false,
   "paymentmethod_is_reward": false,
   "paymentmethod_is_openedgeswipe": false,
   "paymentmethod_update_user_id": 1,
   "paymentmethod_insert_user_id": 1,
   "paymentmethod_insertdate": "2014-10-07 14:53:16",
   "paymentmethod_deleted": false,
   "paymentmethod_is_mobile_visible": true
   }
  ]
}

我使用的包装类称为Table。

代码语言:javascript
复制
data class Table<T>(
    @SerializedName("Table") val models : Array<T>
)

实际的模型类是PaymentMethod。

代码语言:javascript
复制
data class PaymentMethod(
    @SerializedName("paymentmethod_id") val idNumber : Int = -1
)

我已经创建了一个采用类型的通用数据管理器类。我认为使用数据管理器的子类来本地化输入和结果(例如声明模型类PaymentMethod )。

代码语言:javascript
复制
open class NXDataManager<T>(manager: NXNetworkManager? = null, rpc : String?, parameters: List<Pair<String, String>>? = null, method : String = "get")
{
   ...


open fun sendRequest(completionHandler: (models:Array<T>) -> Unit, errorHandler: (error:FuelError) -> Unit) {

    val request = NXNetworkRequest(rpc, parameters, method)

    request.send(manager, completionHandler = { s: String ->

        val table: Table<T> = Gson().fromJson(s)

        completionHandler(table.models)

    }, errorHandler = errorHandler)
}

inline fun <reified T> Gson.fromJson(json: String) = this.fromJson<T>(json, object: TypeToken<T>() {}.type)

}

我的子类数据管理器指定要解析的模型。

代码语言:javascript
复制
final public class PaymentMethodsDataManager : NXDataManager<PaymentMethod>
{
   constructor () : super("genGetPaymentMethods")

}

当我以以下方式运行代码时:

代码语言:javascript
复制
val table: Table<T> = Gson().fromJson(s)

我收到一条错误消息java.lang.ClassCastException:不能将java.lang.Object[]转换为Networking.PaymentMethod[]。但是,当我传递一个显式类型时,它的工作方式与预期一样--将数组解析为PaymentMethod模型:

代码语言:javascript
复制
val table: Table<PaymentMethod> = Gson().fromJson(s)

对我如何仍然可以使用泛型T型有什么想法吗?

EN

回答 3

Stack Overflow用户

发布于 2017-12-28 09:38:10

数据类别:

代码语言:javascript
复制
data class Table<T>(
    @SerializedName("Table") val models : Array<T>
)

转到JSON:

代码语言:javascript
复制
val gson = Gson()
val json = gson.toJson(table)

来自JSON:

代码语言:javascript
复制
val json = getJson()
val table = gson.fromJson(json, Table::class.java)
票数 12
EN

Stack Overflow用户

发布于 2017-12-28 13:51:34

方法fromJson是泛型的,所以当您为Table<T>变量调用它时,它会创建最合适的Array<Any>。您需要注意的是,PaymentMethod类扩展了T泛型,但我不知道这是否可能。如果您找到了如何制作它,请使用如下内容:

代码语言:javascript
复制
val table: Table<T> = Gson().fromJson<Table<PaymentMethod>>(s)

在你的情况下,我使用的是gson适配器。以下函数使用指定的type参数创建对象:

代码语言:javascript
复制
fun getObjectFromString(type: Type, string: String) =
    Gson().getAdapter(TypeToken.get(type)).fromJson(string)

要使用它,请编写以下内容:

代码语言:javascript
复制
val table: Table<T> = getObjectFromString(Table<PaymentMethod>::class.java, s) as Table<PaymentMethod>

更新

为了避免使用备用类强制转换,可以使用reified泛型函数:

代码语言:javascript
复制
inline fun <reified T> getObjectFromString(string: String): T =
            getGsonConverter().getAdapter(TypeToken.get(T::class.java)).fromJson(string)!!

在这种情况下,使用将更容易:

代码语言:javascript
复制
val table: Table<T> = getObjectFromString<Table<PaymentMethod>>(s)

在不知道对象的类型的情况下,我使用了第一个解决方案--我只获得了包含该对象信息的Type变量。

票数 4
EN

Stack Overflow用户

发布于 2018-01-02 11:38:22

java.lang.ClassCastException:不能将java.lang.Object[]转换为Networking.PaymentMethod[]

你的JSON是

代码语言:javascript
复制
{
"Table": [
 {
   "paymentmethod_id": 1,
   "paymentmethod_description": "Cash",
   "paymentmethod_code": "Cash",
   "paymentmethod_is_ach_onfile": false,
   "paymentmethod_is_element": false,
   "paymentmethod_is_reward": false,
   "paymentmethod_is_openedgeswipe": false,
   "paymentmethod_update_user_id": 1,
   "paymentmethod_insert_user_id": 1,
   "paymentmethod_insertdate": "2014-10-07 14:53:16",
   "paymentmethod_deleted": false,
   "paymentmethod_is_mobile_visible": true
   }
  ]
}

创建一个PaymentMethod.,data class

我们经常创建类,其主要目的是保存数据。在这样的类中,一些标准的功能和实用程序函数通常是从数据中机械地派生出来的。

代码语言:javascript
复制
data class PaymentMethod(@SerializedName("Table") val table:ArrayList<PaymentData> )
data class PaymentData

                      (
                       @SerializedName("paymentmethod_id") val paymentmethod_id: Int,
                       @SerializedName("paymentmethod_description") val paymentmethod_description: String,
                       @SerializedName("paymentmethod_code") val paymentmethod_code:String,
                       @SerializedName("paymentmethod_is_ach_onfile") val paidStatus:Boolean,
                       @SerializedName("paymentmethod_is_element") val paymentmethod_is_element:Boolean,
                       @SerializedName("paymentmethod_is_reward") val paymentmethod_is_reward:Boolean,
                       @SerializedName("paymentmethod_is_openedgeswipe") val paymentmethod_is_openedgeswipe:Boolean,
                       @SerializedName("paymentmethod_update_user_id") val paymentmethod_update_user_id:Int,
                       @SerializedName("paymentmethod_insert_user_id") val paymentmethod_insert_user_id:Int,
                       @SerializedName("paymentmethod_insertdate") val paymentmethod_insertdate:String,
                       @SerializedName("paymentmethod_deleted") val paymentmethod_deleted:Boolean),
                       @SerializedName("paymentmethod_is_mobile_visible") val paymentmethod_is_mobile_visible:Boolean
                       )

你可以这样打电话

代码语言:javascript
复制
  val paymentDATA = Gson().fromJson<PaymentMethod>("JSON_RESPONSE", PaymentMethod::class.java)
  val _adapterPaymentHistory = paymentDATA.table
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47944731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档