Retrofit GET请求无法获取货币转换API返回结果问题排查
Retrofit调用RapidAPI货币转换API时response.body为空的解决办法
问题背景
用Retrofit调用RapidAPI上的Currency Converter 18 API发起GET请求,确认URL正确,但response.body()始终返回空值。相关代码如下:
Retrofit接口定义
interface CurrencyConverterEndpoint { @GET("api/v1/convert") fun getCurrencyConverter(@Query("from") from: String, @Query("to") to: String, @Query("amount") amount: String): Call<ConvertModel> }
数据模型类
data class ConvertModel ( @SerializedName("from") val from: String, @SerializedName("to") val to: String, @SerializedName("amountToConvert") val amountToConvert: Int, @SerializedName("convertedAmount") val convertedAmount: Double )
请求调用代码
fun getCurrencyConverter( from: String, to: String, amount: String, listener: RetrofitListener<ConvertModel> ) { val getCurrencyConverterCallback = endpoint.getCurrencyConverter(from, to, amount) getCurrencyConverterCallback.enqueue(object : Callback<ConvertModel> { override fun onResponse(call: Call<ConvertModel>, response: Response<ConvertModel>) { if (response.code() == RetrofitConstants.SUCCESS) { val s = response } } override fun onFailure(call: Call<ConvertModel>, t: Throwable) { listener.onError(t.message ?: "Erro.") } }) }
API返回的JSON结构示例:
{ "status": "success", "data": { "from": "USD", "to": "EUR", "amountToConvert": 100, "convertedAmount": 92.34 } }
问题根源
- 缺少RapidAPI必填请求头:RapidAPI所有接口都要求携带
X-RapidAPI-Key和X-RapidAPI-Host,未添加的话请求会被拒绝,返回内容不符合预期,导致Retrofit解析失败。 - 模型类不匹配返回结构:API返回的是嵌套JSON,外层包含
status和data字段,你直接用ConvertModel对应内层数据,没有外层包装类,Retrofit无法将JSON解析为目标对象。 - 参数类型错误:
amount参数API要求为数值类型,你传入的是String类型,可能导致参数解析异常。
解决步骤
1. 添加RapidAPI请求头
可以在接口方法上直接添加,或在Retrofit客户端全局配置:
interface CurrencyConverterEndpoint { @GET("api/v1/convert") @Headers( "X-RapidAPI-Key: 你的RapidAPI密钥", "X-RapidAPI-Host: currency-converter18.p.rapidapi.com" ) fun getCurrencyConverter( @Query("from") from: String, @Query("to") to: String, @Query("amount") amount: Int // 改为Int类型,匹配API要求 ): Call<CurrencyResponse> }
2. 修正模型类,匹配嵌套结构
新增外层响应类,包裹原有的ConvertModel:
// 外层响应包装类 data class CurrencyResponse( @SerializedName("status") val status: String, @SerializedName("data") val data: ConvertModel ) // 原数据类保持不变 data class ConvertModel ( @SerializedName("from") val from: String, @SerializedName("to") val to: String, @SerializedName("amountToConvert") val amountToConvert: Int, @SerializedName("convertedAmount") val convertedAmount: Double )
3. 调整请求代码适配新响应类型
fun getCurrencyConverter( from: String, to: String, amount: Int, // 同步改为Int类型 listener: RetrofitListener<CurrencyResponse> ) { val callback = endpoint.getCurrencyConverter(from, to, amount) callback.enqueue(object : Callback<CurrencyResponse> { override fun onResponse(call: Call<CurrencyResponse>, response: Response<CurrencyResponse>) { if (response.isSuccessful) { response.body()?.let { // 从响应中取出转换结果 val result = it.data listener.onSuccess(it) } ?: listener.onError("响应体为空") } else { // 打印错误信息方便排查 val errorMsg = response.errorBody()?.string() listener.onError("请求失败:${response.code()},详情:$errorMsg") } } override fun onFailure(call: Call<CurrencyResponse>, t: Throwable) { listener.onError(t.message ?: "请求失败") } }) }
4. 调试技巧
开启Retrofit日志拦截器,查看实际请求和响应内容,快速定位问题:
val loggingInterceptor = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY } val okHttpClient = OkHttpClient.Builder() .addInterceptor(loggingInterceptor) .build() val retrofit = Retrofit.Builder() .baseUrl("https://currency-converter18.p.rapidapi.com/") .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build()
日志会显示请求头、参数、返回的JSON内容,帮助确认问题所在。
内容的提问来源于stack exchange,提问作者Antony Lajes
相关产品推荐
相关产品推荐

