求助: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注解绑定适配器
- 创建一个自定义适配器类,实现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 } }
- 在
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
相关产品推荐
相关产品推荐

