This question may have been asked before but no it was not definitively answered. How exactly does one post raw whole JSON inside the body of a Retrofit request?
See
I tried this: When you are creating your Retrofit instance, add this converter factory to the retrofit builder:
gsonBuilder = new GsonBuilder().serializeNulls()
your_retrofit_instance = Retrofit.Builder().addConverterFactory( GsonConverterFactory.create( gsonBuilder.create() ) )
✅✅✅✅✅✅✅✅✅✅✅✅ Working Solution ✅✅✅✅✅✅✅✅✅✅✅✅
While creating OkHttpClient
that will be used for Retrofit.
add an Interceptor like this.
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()
Now your every Retrofit call's URL and request body will be logged in Logcat
. Filter it by "gsonrequest"
Solved my problem based on TommySM answer (see previous). But I didn't need to make login, I used Retrofit2 for testing https GraphQL API like this:
Defined my BaseResponse class with the help of json annotations (import jackson.annotation.JsonProperty).
public class MyRequest {
@JsonProperty("query")
private String query;
@JsonProperty("operationName")
private String operationName;
@JsonProperty("variables")
private String variables;
public void setQuery(String query) {
this.query = query;
}
public void setOperationName(String operationName) {
this.operationName = operationName;
}
public void setVariables(String variables) {
this.variables = variables;
}
}
Defined the call procedure in the interface:
@POST("/api/apiname")
Call<BaseResponse> apicall(@Body RequestBody params);
Called apicall in the body of test: Create a variable of MyRequest type (for example "myLittleRequest").
Map<String, Object> jsonParams = convertObjectToMap(myLittleRequest);
RequestBody body =
RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),
(new JSONObject(jsonParams)).toString());
response = hereIsYourInterfaceName().apicall(body).execute();
Based on the top answer, I have a solution to not have to make POJOs for every request.
Example, I want to post this JSON.
{
"data" : {
"mobile" : "qwer",
"password" : "qwer"
},
"commom" : {}
}
then, I create a common class like this:
import java.util.Map;
import java.util.HashMap;
public class WRequest {
Map<String, Object> data;
Map<String, Object> common;
public WRequest() {
data = new HashMap<>();
common = new HashMap<>();
}
}
Finally, when I need a json
WRequest request = new WRequest();
request.data.put("type", type);
request.data.put("page", page);
The request marked annotation @Body
then can pass to Retrofit.
Add ScalarsConverterFactory to retrofit:
in gradle:
implementation'com.squareup.retrofit2:converter-scalars:2.5.0'
your retrofit:
retrofit = new Retrofit.Builder()
.baseUrl(WEB_DOMAIN_MAIN)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
change your call interface @Body parameter to String, don't forget to add @Headers("Content-Type: application/json")
:
@Headers("Content-Type: application/json")
@POST("/api/getUsers")
Call<List<Users>> getUsers(@Body String rawJsonString);
now you can post raw json.
I wanted to compare speed of volley and retrofit for sending and receiving data I wrote below code (for retrofit part)
first dependency:
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
}
Then interface:
public interface IHttpRequest {
String BaseUrl="https://example.com/api/";
@POST("NewContract")
Call<JsonElement> register(@Body HashMap registerApiPayload);
}
and a function to set parameters to post data to server(In MainActivity):
private void Retrofit(){
Retrofit retrofitRequest = new Retrofit.Builder()
.baseUrl(IHttpRequest.BaseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
// set data to send
HashMap<String,String> SendData =new HashMap<>();
SendData.put("token","XYXIUNJHJHJHGJHGJHGRTYTRY");
SendData.put("contract_type","0");
SendData.put("StopLess","37000");
SendData.put("StopProfit","48000");
final IHttpRequest request=retrofitRequest.create(IHttpRequest.class);
request.register(SendData).enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
if (response.isSuccessful()){
Toast.makeText(getApplicationContext(),response.body().toString(),Toast.LENGTH_LONG).show();
}
}
@Override
public void onFailure(Call<JsonElement> call, Throwable t) {
}
});
}
And I found Retrofit faster than volley in my case.