Kotlin Android库存应用Retrofit解析报BEGIN_ARRAY与BEGIN_OBJECT错配错误
解析异常与列表填充失效的根因
- 初始泛型层级错配触发解析崩溃:最初将Retrofit接口返回泛型写为
ArrayList<StockOutItemsResult>,相当于指定Gson从JSON根节点开始解析数组,但实际接口返回的根节点是包含success、result、targetUrl字段的全局响应对象,解析器在根节点位置遇到了对象而非数组,直接抛出Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $的异常。 - 泛型修正后的数据链路断链:即便把Retrofit返回泛型调整为全局响应对象类型,后续列表填充环节没有从响应对象中提取嵌套在
result字段内的商品数组,直接把整个响应对象传入ListView Adapter,导致Adapter泛型和实际传入的数据类型不匹配,既无法正确读取列表长度,也拿不到条目数据填充视图。
注:即便已经通过JsonSchema2Pojo生成了全量层级的POJO,只要泛型声明没有顺着JSON结构从根节点逐层对应到目标数据位置,依然会出现解析失败或数据取空的问题。
分步骤适配修复方案
- 对齐Retrofit接口的根层级泛型定义
按照抓包确认的JSON根结构,把对应全局响应类作为Retrofit接口的直接返回类型,禁止跳过分层直接拿内层数组作为根返回类型,参考声明方式:// 已生成的全局响应POJO类,结构对应根JSON:包含success、targetUrl、result字段 data class StockApiResponse( val success: Boolean, val targetUrl: String?, val result: List<StockOutItemsResult> ) // Retrofit接口声明,返回类型直接绑定全局响应类 interface StockService { @GET("stock/outbound/items") suspend fun getStockOutItems(): StockApiResponse } - 打通嵌套数据的提取逻辑
接口返回响应对象后,先做业务层的成功校验,再把嵌套在result字段里的商品数组单独抽离出来,不要把整个响应对象直接传入列表组件:// 接口调用逻辑 val response = stockService.getStockOutItems() if (response.success) { // 单独提取result字段的数组作为列表数据源,空值时兜底传空列表 val stockDataList = response.result ?: emptyList() // 把纯业务数组传给ListView listView.adapter = StockListAdapter(this, stockDataList) } - 对齐Adapter的泛型定义
自定义ListView Adapter的泛型必须和result数组内的元素类型完全一致,Adapter内部仅维护纯业务数据列表,不感知外层全局响应的结构:class StockListAdapter( context: Context, private val dataSource: List<StockOutItemsResult> ) : BaseAdapter() { override fun getCount() = dataSource.size override fun getItem(position: Int) = dataSource[position] override fun getItemId(position: Int) = position.toLong() // 重写getView方法完成条目视图绑定 }
同类接口对接的通用排查规则
- 遇到
Expected BEGIN_XXX类解析异常时,直接顺着报错提示的JSON路径(比如示例里的path $就代表根节点位置),一层一层核对泛型类型和JSON结构的匹配度,不需要一开始就排查POJO内部的字段映射。 - 所有带统一全局响应结构的接口,统一封装泛型的全局响应类,避免每个接口单独重复编写
success、targetUrl这类公共字段的映射。 - 列表类组件的Adapter只接收纯业务数据列表,和外层的接口响应校验、错误处理逻辑完全解耦,避免出现把整个响应对象当列表数据传入的错配问题。
内容的提问来源于stack exchange,提问作者Janou
相关产品推荐
相关产品推荐

