Retrofit2请求API报BEGIN_ARRAY but was BEGIN_OBJECT错误,修改DTO后仍未解决
问题诱因
这个报错是Retrofit的Gson转换器在解析返回数据时,预期数据结构是JSON数组,但实际拿到的是JSON对象导致的:
- 你定义的
LotrRepository中getCharacters()方法返回值为List<CharacterDTO>,告诉Gson要把接口返回内容解析成一个CharacterDTO类型的数组 - 但你给出的接口返回结构最外层是单个JSON对象(包裹了docs、total等字段),完全符合单个
CharacterDTO的结构,和数组没有任何关系。你之前只补充了CharacterDTO的字段,没有修改返回值类型,Gson还是会尝试把外层对象解析为数组,所以报错没有解决。
修复方案
- 调整Repository接口的返回值类型
把getCharacters()的返回值从List<CharacterDTO>改为CharacterDTO,匹配接口实际返回的外层结构:
interface LotrRepository { suspend fun getBooks(): List<BookDTO> // 修改此处返回值类型 suspend fun getCharacters(): CharacterDTO suspend fun getCharacterById(characterId: String): CharacterDTO }
- 修改UseCase中的数据处理逻辑
拿到外层的CharacterDTO对象后,取出里面的docs数组,再转换为业务层需要的Character列表即可:
class GetCharactersUseCase @Inject constructor( private val repository: LotrRepository ) { operator fun invoke(): Flow<List<Character>> = flow { try { val characterDto = repository.getCharacters() // 取出docs列表转换为目标类型 val characterList = characterDto.docs.map { it.toCharacter() } // 发射处理后的列表 emit(characterList) Log.d(Tag, characterList.toString()) } catch (e: HttpException) { Log.d(Tag, e.toString()) } catch (e: IOException) { Log.d(Tag, e.toString()) } } }
- 可选校验
建议同步检查getBooks、getCharacterById两个方法的返回值是否和对应接口的实际返回结构匹配,避免出现同类报错。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

