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

如何使用Retrofit发送Raw格式的POST请求?

问题描述

我是Retrofit及HTTP请求的新手,目前代码结构很不稳定。成功在登录后的请求头中携带JWT字符串后,我想要发起一个POST请求。

Postman中的请求体

{"name":"PlanetX","radius":0}

我的尝试代码

//HashMap<String, Integer> body = new HashMap<String, Integer>();
    //body.put("PlanetX", 0);

    //Planet body = new Planet("PlanetX", 0);

    //String text = "{\"name\":\"PlanetX\",\"radius\":0}";
    //RequestBody body = RequestBody.create(MediaType.parse("text/plain"), text);
    
    JsonObject body = new JsonObject();
    body.addProperty("name", "value1");
    body.addProperty("id", 9);

    call = service.postObject(body);

POST接口定义

@POST("planets")
Call<String> postObject(@Body JsonObject body);
//Call<String> postObject(@Body RequestBody body);
//Call<String> postObject(@Body Planet body);
//Call<String> postObject(@Body HashMap<String, Integer> body);

遇到的错误

多数情况下会收到415状态码,或是如下错误:

java.lang.IllegalArgumentException: Unable to create @Body converter for class com.google.gson.JsonObject (parameter #1)
        for method PlanetRepository.postObject

相关实体类及RestService代码

Planet实体类

public class Planet {

    private long ID;
    private String name;
    private int radius;

    public Planet(String name, int radius ) {
        this.name = name;
        this.radius = radius;
    }
}

RestService类

import android.content.Context;
import android.widget.TextView;
import android.widget.Toast;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.scalars.ScalarsConverterFactory;

public class RestService {

    // Base URL
    private static final String BASE_URL = "http://10.0.2.2:8080/";
    
    // BUILDER GSON
    private static Gson gson= new GsonBuilder()
            .setLenient()
            .create();

    // BUILDER Retrofit
    private static Retrofit.Builder builder
            = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(ScalarsConverterFactory.create());
            //.addConverterFactory(GsonConverterFactory.create(gson));
    private static Retrofit retrofit = builder.build();

    // BUILDER OkHttpClient
    private static OkHttpClient.Builder httpClient
            = new OkHttpClient.Builder();

    // BUILDER Logger
    private static HttpLoggingInterceptor logging
            = new HttpLoggingInterceptor()
            .setLevel(HttpLoggingInterceptor.Level.BASIC);

    // METHOD: Service Generator + Authentication
    public static <S> S Create(Class<S> serviceClass, final String token ) {
        if ( token != null ) {
            httpClient.interceptors().clear();
            httpClient.addInterceptor( chain -> {
                Request original = chain.request();
                Request request = original.newBuilder()
                        //.header("Authorization", token)
                        .header("Authorization", " Bearer "+token)
                        .build();
                return chain.proceed(request);
            });
            httpClient.addInterceptor(logging); // Logger
            builder.client(httpClient.build());
            retrofit = builder.build();
        }
        return retrofit.create(serviceClass);
    }


    // METHOD: Message Generator
    public static void Message(Context c, TextView v, Object o) {
        String message;

        if (o instanceof Response) {
            message ="RESPONSE : \n"
                    +"HEADER :\n "
                    + ((Response<?>) o).headers()
                    +"BODY: \n"
                    + ((Response<?>) o).body()
                    +"\nSTATUS: \n"
                    + ((Response<?>) o).code();
            v.setText(message);
            Toast.makeText(c, message, Toast.LENGTH_LONG).show();

        } else if (o instanceof Throwable) {
            message = "Caught Throwable: \n" + o;
            v.setText(message);
            Toast.makeText(c, message, Toast.LENGTH_LONG).show();
            System.out.println(message);

        } else if (o instanceof Exception) {
            message = "Caught Exception: \n" + o;
            v.setText(message);
            Toast.makeText(c, message, Toast.LENGTH_LONG).show();
            System.out.println(message);

        } else {
            System.out.println("ResponseMessage does not recognizes object");
        }
    }
}

解决方案

核心问题定位

  1. 415状态码:服务器不支持请求的媒体类型,原因是你只配置了ScalarsConverterFactory,缺少JSON序列化的转换器,导致请求体无法以服务器期望的application/json格式发送。
  2. Converter找不到错误:Retrofit没有Gson转换器,无法将JsonObject或Planet对象转换为符合要求的请求体。

步骤1:添加Gson转换器依赖

在Module级别的build.gradle中添加依赖(版本可匹配你的Retrofit版本):

implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

步骤2:启用GsonConverterFactory

修改RestService中的Retrofit构建代码,取消注释Gson转换器配置:

// BUILDER Retrofit
private static Retrofit.Builder builder
        = new Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(ScalarsConverterFactory.create())
        .addConverterFactory(GsonConverterFactory.create(gson)); // 启用这一行
private static Retrofit retrofit = builder.build();

步骤3:用Planet实体类发起请求(推荐规范写法)

这是最贴合Retrofit设计的方式,能自动处理JSON序列化:

  1. 修正Planet实体类字段匹配:
    实体类中ID字段首字母大写,Gson默认会序列化为"ID",如果服务器不需要该字段可直接删除;若需要则添加@SerializedName保证和服务器字段名一致:
    public class Planet {
        // 服务器不需要则删除,需要则添加注解匹配字段名
        @SerializedName("id")
        private long ID;
        private String name;
        private int radius;
    
        public Planet(String name, int radius ) {
            this.name = name;
            this.radius = radius;
        }
    }
    
  2. 接口定义保留Planet参数版本:
    @POST("planets")
    Call<String> postObject(@Body Planet body);
    
  3. 发起请求的代码:
    Planet body = new Planet("PlanetX", 0);
    call = service.postObject(body);
    

额外注意事项

  • 自动设置Content-Type:启用Gson转换器后,Retrofit会自动添加Content-Type: application/json请求头,解决415问题。
  • JWT头格式修正:你的Authorization头写的是" Bearer "+token,前面多了一个空格,建议改为"Bearer "+token,避免部分服务器解析失败。
  • 请求体字段匹配:之前尝试的JsonObject中添加了id字段,但Postman中的请求体没有该字段,要确保请求体字段和服务器要求完全一致。

内容的提问来源于stack exchange,提问作者Wabi-Sabi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 21:55:15