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

求助:Moshi无法识别继承ArrayList的Albums类,如何实现Moshi对该自定义集合类的支持?

解决Moshi无法识别继承自ArrayList的自定义集合类问题

问题背景

你在使用Retrofit+Moshi开发Demo时遇到了JsonDataException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at path $异常:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.anushka.retrofitdemo, PID: 12428
com.squareup.moshi.JsonDataException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at path $
...

原因是你定义了继承自ArrayList<AlbumsItem>的Albums类作为接口返回类型,但Moshi无法自动将JSON数组解析为这个自定义集合类。而改用List<AlbumsItem>或者切换到GsonConverterFactory时则能正常运行。

问题原因

Moshi的类型适配逻辑比Gson更严格:

  • Gson会自动识别继承自集合类的自定义类型,并将其当作集合来解析
  • 但Moshi默认会把Albums这样的自定义类当作普通对象处理,尝试去匹配JSON对象的键值对,而接口返回的是JSON数组,因此抛出类型不匹配的异常

解决方案:为自定义集合类编写Moshi适配器

你需要手动告诉Moshi如何将JSON数组与Albums类进行转换,有两种实现方式:

方式1:使用@JsonAdapter注解绑定适配器

  1. 创建一个自定义适配器类,实现JSON数组与Albums的转换逻辑:
class AlbumsAdapter {
    // 将JSON数组解析为Albums对象
    @FromJson
    fun fromJson(albumsItems: List<AlbumsItem>): Albums {
        val albums = Albums()
        albums.addAll(albumsItems)
        return albums
    }

    // 将Albums对象序列化为JSON数组
    @ToJson
    fun toJson(albums: Albums): List<AlbumsItem> {
        return albums
    }
}
  1. 在Albums类上添加@JsonAdapter注解,指定使用上面的适配器:
@JsonAdapter(AlbumsAdapter::class)
class Albums : ArrayList<AlbumsItem>()

方式2:直接在Moshi实例中注册适配器

如果你不想给Albums类添加注解,可以在创建Moshi实例时直接注册适配器:

var moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .add(AlbumsAdapter()) // 注册自定义适配器
    .build()

验证修改

完成上述配置后,你的原接口定义和调用代码就可以正常工作了:

// 服务接口无需修改
interface AlbumsService {
    @GET("albums")
    suspend fun getAlbums(): Response<Albums>
}

// MainActivity中的调用逻辑也保持原样即可

补充说明

  • 确保你的Moshi实例已经添加了KotlinJsonAdapterFactory,否则Kotlin数据类的适配会出现问题
  • 这种自定义适配器的方式适用于所有需要Moshi特殊处理的自定义集合类型,原理就是明确告诉Moshi类型转换的规则

内容的提问来源于stack exchange,提问作者Dr Mido

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 11:42:30