You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中使用Gson解析JSON数组至Realm对象时遇类型转换异常

解决Realm插入JSON数组时的类型转换异常问题

嘿,我来帮你排查这个问题!你遇到的com.example.android.sunshine.data.Location[] cannot be cast to java.lang.Iterable异常,核心原因是Gson解析时的类型不匹配,再加上一些异步事务和流处理的小问题,咱们一步步来修正:

1. 核心错误:Gson解析的类型不匹配

你这段代码存在类型转换的隐患:

val weatherList = gson.fromJson<List<Location>>(jsonReader , Array<Location>::class.java).toList()

这里你告诉Gson要返回List<Location>,但第二个参数传入的是Array<Location>::class.java,Gson实际会返回Location[]数组,而数组不能直接强制转换为List(虽然你调用了toList(),但前面的类型强转已经会触发异常了)。这就是导致Location[]无法转成Iterable的根源。

2. 修正方案:两种正确的解析方式

你可以任选一种方式来修复解析逻辑:

方式一:直接解析为数组,传给Realm

Realm的insertOrUpdate方法本身支持接收数组参数,所以可以直接用数组来操作:

val locationArray = gson.fromJson(jsonReader, Array<Location>::class.java)
realm.insertOrUpdate(locationArray) // 直接传入数组,Realm支持这种写法

方式二:用TypeToken解析为List

如果你更习惯用List,可以借助TypeToken来指定泛型类型,让Gson直接返回List:

val type = object : TypeToken<List<Location>>() {}.type
val weatherList = gson.fromJson<List<Location>>(jsonReader, type)
realm.insertOrUpdate(weatherList) // List是Iterable的实现,直接传入即可

3. 其他需要调整的问题

(1)不要在异步事务里操作JsonReader

你的jsonReader.endArray()和jsonReader.close()放在了异步事务的回调里,这会导致问题:异步事务是在后台线程执行的,而你在主线程打开的输入流,可能在事务执行前就已经被系统回收,或者流操作的时机不对。应该在主线程完成流的读取和关闭,再把解析好的数据传入事务。

(2)正确管理Realm实例

你直接调用Realm.getDefaultInstance().executeTransactionAsync(...)会导致Realm实例无法被正确关闭,造成资源泄漏。可以用Kotlin的use函数来自动管理实例的生命周期。

完整修正后的代码

private fun loadStuff() {
    val inputStream = this.resources.openRawResource(R.raw.city_json)
    JsonReader(InputStreamReader(inputStream, "UTF-8")).use { jsonReader ->
        val gson = Gson()
        // 先在主线程完成JSON解析
        val locationArray = gson.fromJson(jsonReader, Array<Location>::class.java)
        
        // 用use函数自动管理Realm实例,避免资源泄漏
        Realm.getDefaultInstance().use { realm ->
            realm.executeTransactionAsync({ transactionRealm ->
                transactionRealm.insertOrUpdate(locationArray)
            }, {
                Log.d("TAG", "Success")
            }, { error ->
                Log.e("TAG", "Insert failed", error)
            })
        }
    }
}

额外检查点

  • 你的Location类已经正确添加了@RealmClass注解,并且继承了RealmObject,字段都是open的(Kotlin中Realm需要开放字段来生成代理类),这部分是没问题的。
  • JSON字段和@SerializedName的映射也完全匹配你提供的JSON示例,无需调整。

这样调整后,就能顺利解析JSON数组并插入Realm啦!

内容的提问来源于stack exchange,提问作者Lukas Anda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:32:12