安卓APP中Retrofit POST请求返回400错误排查求助
Hey there! Sorry to hear you're hitting that frustrating 400 Bad Request error with your Retrofit POST call—especially since Postman works perfectly. That discrepancy usually means your app is formatting the request differently than Postman, so let’s walk through the most likely fixes, starting with the POJO classes you suspect.
1. Validate POJO Serialization Annotations & Naming
This is the #1 culprit when Postman works but Retrofit doesn’t. APIs often use snake_case (like genre_id) while Java uses camelCase (genreId), so you need explicit mapping with @SerializedName:
// Incorrect: No mapping for snake_case API fields public class Genre { private int genreId; // API expects "genre_id" } // Correct: Use @SerializedName to match API field names public class Genre { @SerializedName("genre_id") private int genreId; }
- Also, if you’re using
GsonBuilder.excludeFieldsWithoutExposeAnnotation(), make sure all required fields have the@Exposeannotation—missing it will exclude the field from the request body entirely. - Double-check that your POJO has all required fields the API expects (no missing fields, no extra fields that the API rejects).
2. Confirm Request Body Type & Retrofit Setup
Retrofit handles request bodies differently based on annotations—make sure you’re using the right one for your API:
- If your API accepts JSON (like Postman likely does), use
@Body(not@FormUrlEncodedor@Field):// Right for JSON request bodies @POST("movies") Call<Movie> createMovie(@Body Movie movie); // Wrong if API expects JSON (this sends form-data instead) @FormUrlEncoded @POST("movies") Call<Movie> createMovie(@Field("title") String title, @Field("genre") Genre genre); - Verify your Retrofit instance includes
GsonConverterFactory(this tells Retrofit to serialize POJOs to JSON):Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) // Critical for JSON serialization .build(); - Check that your
Content-Typeheader matches Postman’s—Retrofit setsapplication/jsonautomatically when using@Bodyand Gson, but if you’ve added custom headers, make sure they don’t override this.
3. Log the Exact Request Body to Compare with Postman
The fastest way to spot the issue is to see what your app is actually sending. Add HttpLoggingInterceptor to your Retrofit setup to print the full request (including body) to Logcat:
// Add this dependency first if you don't have it: implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0' HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(loggingInterceptor) .build(); // Use this client in your Retrofit instance Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build();
Now check Logcat for the POST request’s body. Compare it line-for-line with the request body you used in Postman. You’ll almost certainly see a mismatch:
- Missing required fields
- Incorrect field names
- Null values where the API expects a non-null value
- Wrong data types (e.g., a String where an Integer is expected)
4. Check for Null Values & Invalid Data
APIs often reject requests with null values for required fields. Make sure when you create your Movie or Genre objects, you’re setting all mandatory fields:
// Bad: Missing required "title" field Movie movie = new Movie(); movie.setGenre(genre); // Good: All required fields are set Movie movie = new Movie(); movie.setTitle("Inception"); movie.setGenre(genre); movie.setReleaseYear(2010);
Also, confirm data types match exactly—if the API expects release_year as an integer, don’t pass it as a String.
5. Verify Endpoint Path & Base URL
Double-check that your API endpoint path matches Postman’s exactly:
- If Postman uses
https://your-api.com/api/v1/movies, make sure your base URL ishttps://your-api.com/api/v1/(ends with a slash) and your endpoint is@POST("movies") - Avoid typos in the path (e.g.,
movieinstead ofmovies) - Ensure you’re using
@POST(not@GETor another HTTP method)
Once you fix the mismatch between your app’s request and Postman’s, that 400 error should disappear and you’ll get the 200 response you’re expecting!
内容的提问来源于stack exchange,提问作者Ahsan Abdullah

