Retrofit中数据类与CaloriesNinja API响应匹配失败问题排查
解决Retrofit调用CaloriesNinja API的解析错误问题
问题现象
调用CaloriesNinja API获取营养数据时,onResponse从未触发,每次都会进入onFailure,报错:
onFailure: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
问题原因
你定义的Retrofit接口返回类型是Call<List<nutritionData>>,但CaloriesNinja API实际返回的是单个对象(该对象包含一个items数组)。Gson解析时期望接收数组(BEGIN_ARRAY),但实际收到的是对象(BEGIN_OBJECT),因此解析失败。
修复步骤
1. 修正API接口的返回类型
将接口返回的Call<List<nutritionData>>改为Call<nutritionData>,匹配API的实际响应格式:
interface NinjaAPI { @GET("v1/nutrition") // 移除末尾的?,Retrofit会自动拼接Query参数 fun getNutrition(@Query("query") foodName: String): Call<nutritionData> }
2. 调整回调的泛型类型
在getMyNutrition方法中,将回调的泛型从List<nutritionData>?改为nutritionData?,对应接口的返回类型:
fun getMyNutrition(foodName: String) { val retrofitBuilder = Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .baseUrl(BASE_URL) .client(client) .build() .create(NinjaAPI::class.java) val retrofitData = retrofitBuilder.getNutrition(foodName) retrofitData.enqueue(object : Callback<nutritionData?> { override fun onResponse( call: Call<nutritionData?>, response: Response<nutritionData?> ) { Log.d(TAG, "IT WORKED") // 处理返回的营养数据 response.body()?.let { data -> data.items.forEach { item -> Log.d(TAG, "食品: ${item.name}, 卡路里: ${item.calories}") } } } override fun onFailure(call: Call<nutritionData?>, t: Throwable) { Log.d(TAG, "onFailure: " + t.message) } }) }
3. 可选:规范数据类命名(符合Kotlin编码规范)
将nutritionData类名改为大写开头的NutritionData,同时同步修改接口和回调中的类型:
data class NutritionData( val items: List<Item> ) // 接口修改为: fun getNutrition(@Query("query") foodName: String): Call<NutritionData> // 回调修改为: retrofitData.enqueue(object : Callback<NutritionData?> { ... })
总结
核心问题是响应类型不匹配,API返回单个对象但代码错误地用数组接收。调整Retrofit接口和回调的返回类型为单个对象后,即可正常解析数据。
内容的提问来源于stack exchange,提问作者AboKaid 999
相关产品推荐
相关产品推荐

