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

Android使用Retrofit+Moshi请求报错Expected a string but was BEGIN_ARRAY求助

问题根因

你的接口返回的JSON根节点是数组类型,但你当前配置了Moshi转换器的Retrofit被要求将响应转为String类型,Moshi解析时发现实际返回值是数组和预期的字符串类型不匹配,就抛出了对应错误。

解决方案

方案1:保留自定义JSON解析逻辑

如果必须保留你现有的parseJsonInfoResults手动解析逻辑,可通过让Retrofit返回原始响应体的方式拿到原始JSON字符串:

  1. 修改接口定义,将返回值改为ResponseBody,跳过Moshi对返回值的自动类型校验:
interface InfoCollections {
    @GET(ENDPOINT)
    suspend fun getInfoService(): ResponseBody
} 
  1. 修改仓库层代码,先获取原始JSON字符串,再用对应根类型解析:
suspend fun fetchInfo(){
    val response = Networking.moshiNetworkingServices.getInfoService()
    val jsonStr = response.string()
    // 根节点为数组,使用JSONArray而非JSONObject
    val feeds = parseJsonInfoResults(JSONArray(jsonStr))
    infoDao.insertAll(*feeds.toTypedArray())
}
  1. 同步修改parseJsonInfoResults方法的入参类型,适配JSONArray输入。

方案2:用Moshi自动解析(更推荐)

直接通过Moshi把响应自动解析为实体类列表,省去手动解析JSON的步骤:

  1. 定义和JSON结构对应的实体类(如果该类同时是Room实体,可直接复用现有Room实体类):
@JsonClass(generateAdapter = true)
data class InfoItem(
    // 按需添加和JSON字段对应的属性
    val id: Int,
    val content: String
)
  1. 修改接口返回值为实体类列表:
interface InfoCollections {
    @GET(ENDPOINT)
    suspend fun getInfoService(): List<InfoItem>
} 
  1. 仓库层直接使用解析完成的列表操作数据库:
suspend fun fetchInfo(){
    val feeds = Networking.moshiNetworkingServices.getInfoService()
    infoDao.insertAll(*feeds.toTypedArray())
}

注意事项

  • 已配置JSON转换器的Retrofit不要直接使用String作为响应类型,转换器会尝试把JSON内容转为String,遇到数组/对象类型就会触发类型不匹配错误
  • 手动解析JSON前先确认根节点类型,根为数组用JSONArray,根为对象才用JSONObject

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 13:45:04