Android/Kotlin/Retrofit中带Body的GET请求返回布尔值问题排查
解决方案
问题1:GET请求携带请求体不被Retrofit支持
HTTP规范中GET请求通常不携带请求体,尽管部分服务器允许,但Retrofit默认不会为GET请求发送请求体。需要给OkHttpClient添加拦截器,通过请求伪装实现GET带Body的需求:
val okHttpClient = OkHttpClient.Builder() .addInterceptor { chain -> val originalRequest = chain.request() if (originalRequest.method == "GET" && originalRequest.body != null) { // 用POST发送请求,通过请求头告知服务器实际是GET请求 val modifiedRequest = originalRequest.newBuilder() .method("POST", originalRequest.body) .header("X-HTTP-Method-Override", "GET") .build() chain.proceed(modifiedRequest) } else { chain.proceed(originalRequest) } } .build()
将配置好的OkHttpClient传入Retrofit实例:
val retrofit = Retrofit.Builder() .baseUrl(BASE_URL) .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build()
问题2:裸布尔值响应解析失败
接口返回的true/false属于裸JSON值,Gson默认无法直接解析为Boolean类型,有两种解决方式:
方案A:手动解析ResponseBody
修改API接口定义,直接返回ResponseBody:
@GET("api/is_correct") suspend fun isCorrect(@Body email: Email): ResponseBody
在ViewModel中手动读取并解析:
fun checkIfCorrect(input: String) { val email = Email(input) viewModelScope.launch { try { val responseBody = RetrofitInstance.api.isCorrect(email) val result = responseBody.string().toBooleanStrict() Log.e(TAG, "校验结果:$result") } catch (e: Exception){ Log.e(TAG, "错误详情:${e.message}") } } }
方案B:自定义Gson转换器支持裸值解析
创建布尔值的自定义TypeAdapter:
class BooleanTypeAdapter : TypeAdapter<Boolean>() { override fun write(out: JsonWriter, value: Boolean?) { out.value(value) } override fun read(`in`: JsonReader): Boolean { return when (`in`.peek()) { JsonToken.BOOLEAN -> `in`.nextBoolean() JsonToken.STRING -> `in`.nextString().toBooleanStrict() JsonToken.NUMBER -> `in`.nextDouble() != 0.0 else -> throw JsonSyntaxException("预期布尔值,实际为${`in`.peek()}") } } }
注册适配器到Gson实例:
val gson = GsonBuilder() .registerTypeAdapter(Boolean::class.java, BooleanTypeAdapter()) .registerTypeAdapter(Boolean::class.javaObjectType, BooleanTypeAdapter()) .create()
将自定义Gson传入Retrofit:
val retrofit = Retrofit.Builder() .baseUrl(BASE_URL) .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create(gson)) .build()
此时API接口可继续使用Response<Boolean>作为返回类型:
@GET("api/is_correct") suspend fun isCorrect(@Body email: Email): Response<Boolean>
额外建议
- 优先选择方案A,配置简单且避免自定义转换器的潜在问题。
- 若条件允许,建议和后端沟通调整接口:要么改为POST请求携带Body,要么将布尔值包装为标准JSON对象(如
{"result": true}),更符合HTTP规范和常规接口设计。
内容的提问来源于stack exchange,提问作者ubewafersticks
相关产品推荐
相关产品推荐

