Android使用Retrofit+Moshi请求报错Expected a string but was BEGIN_ARRAY求助
问题根因
你的接口返回的JSON根节点是数组类型,但你当前配置了Moshi转换器的Retrofit被要求将响应转为String类型,Moshi解析时发现实际返回值是数组和预期的字符串类型不匹配,就抛出了对应错误。
解决方案
方案1:保留自定义JSON解析逻辑
如果必须保留你现有的parseJsonInfoResults手动解析逻辑,可通过让Retrofit返回原始响应体的方式拿到原始JSON字符串:
- 修改接口定义,将返回值改为
ResponseBody,跳过Moshi对返回值的自动类型校验:
interface InfoCollections { @GET(ENDPOINT) suspend fun getInfoService(): ResponseBody }
- 修改仓库层代码,先获取原始JSON字符串,再用对应根类型解析:
suspend fun fetchInfo(){ val response = Networking.moshiNetworkingServices.getInfoService() val jsonStr = response.string() // 根节点为数组,使用JSONArray而非JSONObject val feeds = parseJsonInfoResults(JSONArray(jsonStr)) infoDao.insertAll(*feeds.toTypedArray()) }
- 同步修改
parseJsonInfoResults方法的入参类型,适配JSONArray输入。
方案2:用Moshi自动解析(更推荐)
直接通过Moshi把响应自动解析为实体类列表,省去手动解析JSON的步骤:
- 定义和JSON结构对应的实体类(如果该类同时是Room实体,可直接复用现有Room实体类):
@JsonClass(generateAdapter = true) data class InfoItem( // 按需添加和JSON字段对应的属性 val id: Int, val content: String )
- 修改接口返回值为实体类列表:
interface InfoCollections { @GET(ENDPOINT) suspend fun getInfoService(): List<InfoItem> }
- 仓库层直接使用解析完成的列表操作数据库:
suspend fun fetchInfo(){ val feeds = Networking.moshiNetworkingServices.getInfoService() infoDao.insertAll(*feeds.toTypedArray()) }
注意事项
- 已配置JSON转换器的Retrofit不要直接使用
String作为响应类型,转换器会尝试把JSON内容转为String,遇到数组/对象类型就会触发类型不匹配错误 - 手动解析JSON前先确认根节点类型,根为数组用
JSONArray,根为对象才用JSONObject
内容的提问来源于stack exchange,提问作者OEThe11
相关产品推荐
相关产品推荐

