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
1)Add dependencies-
compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
2) make Api Handler class
public class ApiHandler {
public static final String BASE_URL = "URL";
private static Webservices apiService;
public static Webservices getApiService() {
if (apiService == null) {
Gson gson = new GsonBuilder()
.setLenient()
.create();
Retrofit retrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)).baseUrl(BASE_URL).build();
apiService = retrofit.create(Webservices.class);
return apiService;
} else {
return apiService;
}
}
}
3)make bean classes from Json schema 2 pojo
Remember
-Target language : Java -Source type : JSON -Annotation style : Gson -select Include getters and setters -also you may select Allow additional properties
http://www.jsonschema2pojo.org/
4)make interface fro api calling
public interface Webservices {
@POST("ApiUrlpath")
Call<ResponseBean> ApiName(@Body JsonObject jsonBody);
}
if you have a form-data parameters then add below line
@Headers("Content-Type: application/x-www-form-urlencoded")
Other way for form-data parameter check this link
5)make JsonObject for passing in to body as parameter
private JsonObject ApiJsonMap() {
JsonObject gsonObject = new JsonObject();
try {
JSONObject jsonObj_ = new JSONObject();
jsonObj_.put("key", "value");
jsonObj_.put("key", "value");
jsonObj_.put("key", "value");
JsonParser jsonParser = new JsonParser();
gsonObject = (JsonObject) jsonParser.parse(jsonObj_.toString());
//print parameter
Log.e("MY gson.JSON: ", "AS PARAMETER " + gsonObject);
} catch (JSONException e) {
e.printStackTrace();
}
return gsonObject;
}
6) Call Api Like this
private void ApiCallMethod() {
try {
if (CommonUtils.isConnectingToInternet(MyActivity.this)) {
final ProgressDialog dialog;
dialog = new ProgressDialog(MyActivity.this);
dialog.setMessage("Loading...");
dialog.setCanceledOnTouchOutside(false);
dialog.show();
Call<ResponseBean> registerCall = ApiHandler.getApiService().ApiName(ApiJsonMap());
registerCall.enqueue(new retrofit2.Callback<ResponseBean>() {
@Override
public void onResponse(Call<ResponseBean> registerCall, retrofit2.Response<ResponseBean> response) {
try {
//print respone
Log.e(" Full json gson => ", new Gson().toJson(response));
JSONObject jsonObj = new JSONObject(new Gson().toJson(response).toString());
Log.e(" responce => ", jsonObj.getJSONObject("body").toString());
if (response.isSuccessful()) {
dialog.dismiss();
int success = response.body().getSuccess();
if (success == 1) {
} else if (success == 0) {
}
} else {
dialog.dismiss();
}
} catch (Exception e) {
e.printStackTrace();
try {
Log.e("Tag", "error=" + e.toString());
dialog.dismiss();
} catch (Resources.NotFoundException e1) {
e1.printStackTrace();
}
}
}
@Override
public void onFailure(Call<ResponseBean> call, Throwable t) {
try {
Log.e("Tag", "error" + t.toString());
dialog.dismiss();
} catch (Resources.NotFoundException e) {
e.printStackTrace();
}
}
});
} else {
Log.e("Tag", "error= Alert no internet");
}
} catch (Resources.NotFoundException e) {
e.printStackTrace();
}
}
This is what works me for the current version of retrofit 2.6.2,
First of all, we need to add a Scalars Converter to the list of our Gradle dependencies, which would take care of converting java.lang.String objects to text/plain request bodies,
implementation'com.squareup.retrofit2:converter-scalars:2.6.2'
Then, we need to pass a converter factory to our Retrofit builder. It will later tell Retrofit how to convert the @Body parameter passed to the service.
private val retrofitBuilder: Retrofit.Builder by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
}
Note: In my retrofit builder i have two converters
GsonandScalarsyou can use both of them but to send Json body we need to focusScalarsso if you don't needGsonremove it
Then Retrofit service with a String body parameter.
@Headers("Content-Type: application/json")
@POST("users")
fun saveUser(@Body user: String): Response<MyResponse>
Then create the JSON body
val user = JsonObject()
user.addProperty("id", 001)
user.addProperty("name", "Name")
Call your service
RetrofitService.myApi.saveUser(user.toString())
use following to send json
final JSONObject jsonBody = new JSONObject();
try {
jsonBody.put("key", "value");
} catch (JSONException e){
e.printStackTrace();
}
RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),(jsonBody).toString());
and pass it to url
@Body RequestBody key
1) Make sure to add the following header and remove any other duplicate header. Since, on Retrofit's official documentation they specifically mention-
Note that headers do not overwrite each other. All headers with the same name will be included in the request.
@Headers({"Content-Type: application/json"})
2) a. If you are using a converter factory you can pass your json as a String, JSONObject, JsonObject and even a POJO. Also have checked, having ScalarConverterFactory is not necessary only GsonConverterFactory does the job.
@POST("/urlPath")
@FormUrlEncoded
Call<Response> myApi(@Header("Authorization") String auth, @Header("KEY") String key,
@Body JsonObject/POJO/String requestBody);
2) b. If you are NOT using any converter factory then you MUST use okhttp3's RequestBody as Retrofit's documentation says-
The object will also be converted using a converter specified on the Retrofit instance. If no converter is added, only RequestBody can be used.
RequestBody requestBody=RequestBody.create(MediaType.parse("application/json; charset=utf-8"),jsonString);
@POST("/urlPath")
@FormUrlEncoded
Call<Response> myApi(@Header("Authorization") String auth, @Header("KEY") String key,
@Body RequestBody requestBody);
3) Success!!
You can use hashmap if you don't want to create pojo class for every API call.
HashMap<String,String> hashMap=new HashMap<>();
hashMap.put("email","this@gmail.com");
hashMap.put("password","1234");
And then send like this
Call<JsonElement> register(@Body HashMap registerApiPayload);
After so much effort, found that the basic difference is you need to send the JsonObject instead of JSONObject as parameter.