这个问题以前可能被问过,但没有明确的答案。如何在Retrofit请求的主体中发布原始的整个JSON ?

在这里看到类似的问题。或者这个答案是正确的,它必须是表单url编码并作为一个字段传递?我真的希望不是,因为我要连接的服务只是希望在文章正文中有原始JSON。它们不是用来为JSON数据寻找特定字段的。

I just want to clarify this with the restperts once and for all. One person answered not to use Retrofit. The other was not certain of the syntax. Another thinks yes it can be done but only if its form url-encoded and placed in a field (that's not acceptable in my case). No, I can't re-code all the services for my Android client. And yes, it's very common in major projects to post raw JSON instead of passing over JSON content as field property values. Let's get it right and move on. Can someone point to the documentation or example that shows how this is done? Or provide a valid reason why it can/should not be done.

更新:有一件事我可以百分之百确定。你可以在谷歌的Volley中做到这一点。这是与生俱来的。我们可以在Retrofit中这样做吗?


当前回答

添加ScalarsConverterFactory进行改造:

在gradle:

implementation'com.squareup.retrofit2:converter-scalars:2.5.0'

你的改造:

retrofit = new Retrofit.Builder()
            .baseUrl(WEB_DOMAIN_MAIN)
            .addConverterFactory(ScalarsConverterFactory.create())
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build();

改变你的调用接口@Body参数为String,不要忘记添加@Headers("Content-Type: application/json"):

@Headers("Content-Type: application/json")
@POST("/api/getUsers")
Call<List<Users>> getUsers(@Body String rawJsonString);

现在你可以发布raw json了。

其他回答

我特别喜欢Jake对上面TypedString子类的建议。实际上,您可以基于计划推送的POST数据类型创建各种子类,每个子类都有自己的自定义一致调整集。

您还可以选择在您的Retrofit API中为您的JSON POST方法添加头注释…

@Headers( "Content-Type: application/json" )
@POST("/json/foo/bar/")
Response fubar( @Body TypedString sJsonBody ) ;

但是使用子类显然是自文档化的。

@POST("/json/foo/bar")
Response fubar( @Body TypedJsonString jsonBody ) ;

添加ScalarsConverterFactory.create()方法并传递硬代码

在Retrofit2中,当你想要发送原始参数时,你必须使用标量。

首先在gradle中添加这个:

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'

你的界面

public interface ApiInterface {

    String URL_BASE = "http://10.157.102.22/rest/";

    @Headers("Content-Type: application/json")
    @POST("login")
    Call<User> getUser(@Body String body);

}

活动

   public class SampleActivity extends AppCompatActivity implements Callback<User> {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiInterface.URL_BASE)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        ApiInterface apiInterface = retrofit.create(ApiInterface.class);


        // prepare call in Retrofit 2.0
        try {
            JSONObject paramObject = new JSONObject();
            paramObject.put("email", "sample@gmail.com");
            paramObject.put("pass", "4384984938943");

            Call<User> userCall = apiInterface.getUser(paramObject.toString());
            userCall.enqueue(this);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void onResponse(Call<User> call, Response<User> response) {
    }

    @Override
    public void onFailure(Call<User> call, Throwable t) {
    }
}

JSONObject显示错误,请使用

JsonObject paramObject = new JsonObject(); paramObject.addProperty(“loginId”, vMobile_Email);

在创建OkHttpClient时,将用于Retrofit。

像这样增加一个拦截器。

 private val httpClient = OkHttpClient.Builder()
        .addInterceptor (other interceptors)
        ........................................

        //This Interceptor is the main logging Interceptor
        .addInterceptor { chain ->
            val request = chain.request()
            val jsonObj = JSONObject(Gson().toJson(request))

            val requestBody = (jsonObj
            ?.getJSONObject("tags")
            ?.getJSONObject("class retrofit2.Invocation")
            ?.getJSONArray("arguments")?.get(0) ?: "").toString()
            val url = jsonObj?.getJSONObject("url")?.getString("url") ?: ""
            
            Timber.d("gsonrequest request url: $url")
            Timber.d("gsonrequest body :$requestBody")

            chain.proceed(request)
        }
        
        ..............
        // Add other configurations
        .build()

现在,您的每个Retrofit调用的URL和请求正文将被记录在Logcat中。用"gsonrequest"过滤