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

Retrofit Post请求返回空响应,查阅Stack相关问题未获解求助

排查Retrofit Post请求空响应的实用步骤

我来帮你捋捋这个问题——PostMan能正常拿到数据,说明后端接口本身没问题,问题大概率出在Retrofit的配置、请求体格式或者序列化环节,咱们一步步来排查:

1. 补全并检查Gson转换器的配置

你提到ApiClient里用了GsonConverterFactory但代码没写完,首先得确保这个配置完整,且没有遗漏OkHttpClient的基础配置:

object ApiClient {
    val BASE_URL = "http://MyIpaddress:3005/api/"
    private var retrofit: Retrofit? = null

    val client: Retrofit
        get() {
            if (retrofit == null) {
                // 基础OkHttpClient配置
                val okHttpClient = OkHttpClient.Builder().build()
                
                retrofit = Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create()) // 别漏了create()方法
                    .client(okHttpClient)
                    .build()
            }
            return retrofit!!
        }
}

如果后端返回的字段名和你的POJO字段大小写/命名不匹配,Gson会直接解析出空对象,这是非常常见的坑。

2. 检查LoginModel的序列化注解是否正确

假设PostMan里后端返回的JSON格式是这样:

{
  "username": "test_user",
  "token": "abc_123_token"
}

你的LoginModel必须保证字段名完全匹配,或者用@SerializedName注解做映射:

Java版本

public class LoginModel {
    // 若后端字段是user_name,这里需写成@SerializedName("user_name")
    @SerializedName("username")
    private String username;
    @SerializedName("token")
    private String token;

    // 务必补充对应的getter/setter方法
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getToken() { return token; }
    public void setToken(String token) { this.token = token; }
}

Kotlin版本(推荐用data class)

data class LoginModel(
    @SerializedName("username") val username: String?,
    @SerializedName("token") val token: String?
)

⚠️ 重点提示:Kotlin字段一定要加?设为可空类型,如果后端返回某个字段为null,Gson会直接解析失败,导致整个对象为空。

3. 确保Retrofit接口定义和PostMan请求方式完全匹配

这是最容易踩的坑!比如PostMan用form-data或x-www-form-urlencoded提交参数,但Retrofit用@Body发送JSON,两者完全不兼容:

情况1:PostMan用JSON请求体(Raw/JSON格式)

ApiService应该这么定义:

interface ApiService {
    @POST("login") // 路径要和BASE_URL拼接后与PostMan地址一致
    suspend fun login(@Body loginModel: LoginModel): Response<LoginModel>
    // 不用协程的话,替换为Call<LoginModel>即可
}

情况2:PostMan用表单提交(form-data/x-www-form-urlencoded)

需改用@FormUrlEncoded注解:

interface ApiService {
    @FormUrlEncoded
    @POST("login")
    suspend fun login(
        @Field("username") username: String,
        @Field("token") token: String
    ): Response<LoginModel>
}

必须和PostMan的请求方式完全对应,否则后端接不到参数,自然返回空响应。

4. 添加OkHttp日志拦截器,查看真实请求/响应

这是排查问题的核心步骤!能帮你直观看到Retrofit实际发送的请求和PostMan的差异:
首先在app/build.gradle中添加依赖:

implementation "com.squareup.okhttp3:logging-interceptor:4.11.0"

然后修改ApiClient的OkHttpClient配置:

val loggingInterceptor = HttpLoggingInterceptor().apply {
    level = HttpLoggingInterceptor.Level.BODY // 打印完整的请求头、请求体、响应头、响应体
}

val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(loggingInterceptor)
    .build()

查看Logcat输出:

  • 对比PostMan的请求URL、请求头(比如Content-Type)、请求体是否完全一致
  • 观察后端返回的响应体:如果后端返回空JSON,问题在后端;如果返回正常JSON但Retrofit解析为空,那就是序列化的问题

5. 正确处理Retrofit响应,不要直接取body()

有时候返回空是因为响应码不是2xx,或者响应体本身为空,用Response<T>获取完整响应信息:

// 协程示例
coroutineScope.launch {
    try {
        val apiService = ApiClient.client.create(ApiService::class.java)
        val response = apiService.login(loginModel)
        if (response.isSuccessful) {
            val loginResult = response.body()
            if (loginResult == null) {
                // 打印原始响应内容排查
                Log.d("RetrofitDebug", "Raw response body: ${response.raw().body()?.string()}")
            } else {
                // 正常处理数据
            }
        } else {
            // 响应码错误,打印错误详情
            Log.d("RetrofitDebug", "Request failed: ${response.code()} - ${response.message()}")
        }
    } catch (e: Exception) {
        // 捕获网络异常
        e.printStackTrace()
    }
}

6. 检查BASE_URL的结尾格式

你的BASE_URL是http://MyIpaddress:3005/api/,要确保结尾带有/,接口路径写login,拼接后为http://MyIpaddress:3005/api/login,和PostMan地址完全一致。如果BASE_URL没加/,接口路径需写成/login,格式要统一。


按照上面的步骤排查,重点关注日志拦截器的输出,对比PostMan的请求细节,应该能快速定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:01:55