I have to send the JSON as a Post request through Retrofit. To this I have created a Json Object :
private JSONObject yourJSON(){
JSONObject jsonRoot = new JSONObject();
JSONObject jsonObject1 = new JSONObject();
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject2 = new JSONObject();
try{
jsonArray.put(jsonObject2);
jsonObject2.put("duration", "12");
jsonObject1.put("region", "NYC");
jsonObject1.put("or", jsonArray);
jsonRoot.put("q", jsonObject1);
jsonRoot.put("sort", "recent");
}catch (JSONException e){
e.printStackTrace();
}
return jsonRoot;
}
Then I am using this JSON to send the data by following code
RestApiAdapter restAdapter = new RestApiAdapter();
RoomListingAPI apiservice = restAdapter.providesRestAdapter().create(RoomListingAPI.class);
JSONObject response = apiservice.getRoomListing("qwerty","application/json", yourJSON());
API method
public interface RoomListingAPI {
#POST("/api/listings/search")
JSONObject getRoomListing(#Header("x-parse-session-token") String token, #Header("Content-Type") String type, #Body JSONObject json);
}
My goal is to send the JSON and received the JSON but it's not working. What I am doing wrong here. I am also sending the correct JSON. What I am doing wrong here?
You should call your network operation on a background task instead. Otherwise, NetworkOnMainThreadException will be thrown.
Now retrofit has two modes. Synchronous or Asynchronous.
You're using a synchronous mode, presumably called in your main thread.
What you can do now is to change to asynchronous mode (using retrofit callback).
That is, change from:
public interface RoomListingAPI {
#POST("/api/listings/search")
JSONObject getRoomListing(#Header("x-parse-session-token") String token, #Header("Content-Type") String type, #Body JSONObject json);
}
To:
public interface RoomListingAPI {
#POST("/api/listings/search")
void getRoomListing(#Header("x-parse-session-token") String token, #Header("Content-Type") String type, #Body JSONObject json, Callback<JsonObject> responseCallback);
}
To get the JsonObject return response:
apiservice.getRoomListing("qwerty","application/json", yourJSON(),
new Callback<JsonObject>() {
#Override
public void success(JsonObject jsonObject, Response response) {
// jsonObject is what you're looking for
}
#Override
public void failure(RetrofitError error) {
// do something with the error
}
});
Also, it's better to use gson library. Thus use JsonObject instead of JSONObject. Different letter-case, different library, better performance.
Related
I have a RESTful API running in my local machine which returns a response in JSON (Actually this JSON is the response of nodejs Soap client request) depending on the request. For this particular case I receive POST request from an Android client and return the following response:
{
QueryAcctBalResponse: {
BalExDtoList: {
BalExDto: [{
BalID: "xxxx",
AcctResID: "xxxx",
AcctResName: "xxxx",
BalType: "xxxx",
Balance: "xxxx",
EffDate: "xxxx",
ExpDate: "xxxx",
UpdateDate: "xxxx"
}, {
BalID: "yyyy",
AcctResID: "yyyy",
AcctResName: "yyyy",
BalType: "yyyy",
Balance: "yyyy",
EffDate: "yyyy",
ExpDate: "yyyy",
UpdateDate: "yyyy"
}]
}
}
}
The problem is each time I try to parse that response and display this information in android (Particularly "AcctResName"). I get org.json.JSONException: No value for BalExDto. I use Volley Libray in android to parse Json and i used Jsonobject request.
Request Code.
JsonObjectRequest sq = new JsonObjectRequest(Request.Method.POST, balanceUrl, request, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("BalExDto");
for (int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject=jsonArray.getJSONObject(i);
Toast.makeText(CheckBalance.this, ""+jsonObject.get("AcctResName"), Toast.LENGTH_LONG).show();
}
pd.hide();
} catch (JSONException e) {
e.printStackTrace();
}
Log.d("Response", "Response_TAG: "+response);
}
It's because you don't have a JSON Array, you have a JSON Object.
First of all, you need to get the JSON object from your API response,
JSONObject jsonObject = response.getJSONObject("QueryAcctBalResponse")
and inside that JSON object is the JSON Array.
JSONArray jsonArray = response.getJSONArray("BalExDtoList");
The error says - you are parsing BalExDto wrong. BalExDto is not direct child of response. So you have to parse QueryAcctBalResponse and BalExDtoList and then you can get BalExDto. Because BalExDto is inside BalExDtoList and BalExDtoList is inside QueryAcctBalResponse.
JsonObjectRequest sq = new JsonObjectRequest(Request.Method.POST, balanceUrl, request, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONObject queryAcctBalResponse = response.getJSONObject("QueryAcctBalResponse");
JSONObject balExDtoList = queryAcctBalResponse.getJSONObject("BalExDtoList");
JSONArray jsonArray = balExDtoList.getJSONArray("BalExDto");
for (int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject=jsonArray.getJSONObject(i);
Toast.makeText(CheckBalance.this, ""+jsonObject.get("AcctResName"), Toast.LENGTH_LONG).show();
}
pd.hide();
} catch (JSONException e) {
e.printStackTrace();
}
Log.d("Response", "Response_TAG: "+response);
}
BalExDto array is not the direct child of the response. It is inside BalExDtoList which is inside QueryAcctBalResponseobject. You can not directly access any node in the JSON, you need to traverse the full path before you could access them.
You need to get the array like below
JSONObject queryAcctBalResponse = response.getJSONObject("QueryAcctBalResponse");
JSONObject balExDtoList = queryAcctBalResponse.getJSONObject("BalExDtoList");
JSONArray jsonArray = balExDtoList.getJSONArray("BalExDto");
I need to implement login API in android. For that, I used RestClientHelper, a 3rd Party library in android https://github.com/ravi123shanker/SimpleRestClientHelper
But i need to send a json object to url like:
{
"id":1,
"username":"hello",
"password":"1223"
}
From thier documentation i able to put value to postParams like :
{login=[{"id":1,"password":"hello","username":"1223"}]}
But I need to send like the above format! How could I do that:
my function is:
JSONArray productsJson = new JSONArray();
try {
JSONObject eachProduct = new JSONObject();
eachProduct.put("fcmid", fcm_id);
eachProduct.put("password", pin);
eachProduct.put("username", username);
productsJson.put(eachProduct);
}
catch (Exception e){
Log.e("Exception", "error");
}
ArrayMap<String, Object> postParams=new ArrayMap<>();
postParams.put("login", productsJson.toString());
Log.e("postParams","data "+postParams.toString());
RestClientHelper.getInstance().post(Constants.BASE_URL_USER_LOGIN , postParams, new RestClientHelper.RestClientListener() {
#Override
public void onSuccess(String response) {
}
#Override
public void onError(String error) {
}
});
Any Help, please??
It seems like you need to insert your JsonObject into a JsonArray and then bind it to the login parameter
JSONArray jArray = new JSONArray();
jArray.put(productsJson);
...
postParams.put("login", jArray.toString());
I am trying to integrate greendao with the retrofit. This link will give an idea ( https://i.stack.imgur.com/7qmbu.jpg) of how the data is sent to the server. It is a post request and I am really confused about how to call this request via retrofit.
It will be really helpful if someone can help me with it.
In API response I am getting an request object, response object, message and status code.
response object I have fields about the user and in request object I have field about the information that is being send.
another picture here
https://i.stack.imgur.com/a5DBz.jpg
You can create response like this using this method
private String create(String email, String password) {
try {
JSONObject cell1 = new JSONObject();
JSONObject jsonObject = new JSONObject();
cell1.put("email", email);
cell1.put("password", password);
jsonObject.put("data", cell1);
return jsonObject.toString();
} catch (Exception e) {
return e.getMessage();
}
}
Call you POST as this
#FormUrlEncoded
#POST("your_path_here")
Call<String> uploadData(#Body String obj);
in your Activity
String json = create("your_email", "your_password");
apiInterface.uploadData(json).enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
}
#Override
public void onFailure(Call<String> call, Throwable t) {
}
});
http://www.superbinstruments.com/directory/index.php?r=webservice/profile/id/4096
Here i want to pass ID in the URL (like above) and JsonObject (can be null) in the Body.
Here the concept is like when i pass null to the json object it will retrieve the profile data or if i pass the json object with profile information then it will update the profile data.
I have tried below methods but i can retrieve the data but i can not update the data.
To update the data we we can pass same JSON response as Body.
#POST("index.php")
Call<UserProfile> profileUser(#Query("r") String value, #Body String user);
#POST("index.php?")
Call<UserProfile> saveUser(#Query("r") String value, #Body JSONObject user);
I am passing like:
value= webservice/profile/id/4096
if I pass as Json String as profile updated info then i am getting
"Invalid request password not needed."
OR
if I will pass as JsonObject as profile updated info
then i am getting
java.lang.OutOfMemoryError: OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack trace available
The link you have posted not required any body to post. Remove Body from your code. To use #Field you have to annotate method as #FormUrlEncoded
Your method should be like this.
#FormUrlEncoded
#POST("index.php?r=webservice/profile/id/")
Call<UserProfile> saveUser(#Field("value") String value);
Hope it helps:)
Please try this way
#POST("index.php")
Call<User> getInstruments(#Query("r") String webservice, #Body User user);
And you should have to pass JSON using your model class as Bhuvanesh suggested
JSONObject jObj = null;
try {
jObj = new JSONObject();
jObj.put("firstname", "Kunjan Shah");
} catch (JSONException ex) {
ex.printStackTrace();
}
User user = new User();
user.setData(jObj);
And here is your model class
public class User {
public String getSuccess() {
return success;
}
public void setSuccess(String success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public JSONObject getData() {
return data;
}
public void setData(JSONObject data) {
this.data = data;
}
String success;
String message;
JSONObject data;
}
And call your service by passing this two parameter
Call update_user_profile =
yourapiinterfaceobject.getInstruments("webservice/profile/id/4096", user);
I am using retrofit to get data from http URL.
My Interface Class :
public interface SlotsAPI {
/*Retrofit get annotation with our URL
And our method that will return a Json Object
*/
#GET(url)
retrofit.Call<JSONObject> getSlots();
}
My request method.
public void getResponse(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
//Creating an object of our api interface
SlotsAPI api = retrofit.create(SlotsAPI.class);
retrofit.Call<JSONObject> callback = api.getSlots();
callback.enqueue(new Callback<JSONObject>() {
#Override
public void onResponse(Response<JSONObject> response) {
if (response != null) {
Log.d("OnResponse", response.body().toString());
}
}
#Override
public void onFailure(Throwable t) {
t.printStackTrace();
}
});
}
In the response I am receiving an empty body.And the server responds with 200 OK.
D/OnResponse: {}
But when I open the URL in browser I am getting JSONObject on the screen.
you should try like this way ....
public interface SlotsAPI {
/*Retrofit get annotation with our URL
And our method that will return a Json Object
*/
#GET(url)
Call<JsonElement> getSlots();
}
in request method
retrofit.Call<JsonElement> callback = api.getSlots();
callback.enqueue(new Callback<JsonElement>() {
#Override
public void onResponse(Response<JsonElement> response) {
if (response != null) {
Log.d("OnResponse", response.body().toString());
}
}
Please check your JsonObject. If you want to get response in json you must be define a response type JsonObject not JSONObject other wise specify the pojo class in your interface.
I think you are not understanding the retrofit filosofy.
The correct interface should be:
public interface SlotsAPI {
/*Retrofit get annotation with our URL
And our method that will return a Json Object
*/
#GET(url)
JSONObject getSlots();
}
When you call the getSlots method, retrofit will automatically do the HTTP request and return the JSONObject.
You will need to do this out of the main thread.
Make sure that the url of #Get is relative path
#Base URL: always ends with /
#Url: DO NOT start with /
Example:
String URL = http://api.co/base/ ;
And
#GET("webservice/syncdown")
JSONObject getSlots();
You may receiving a list of Slots. the Gson converter will handle it if you sending array of json
#GET(url)
retrofit.Call<List<Slot>> getSlots();
You are using the retrofit 2 or 1? The version 2 still is in beta.
If you are using the version 1. Use this:
public interface SlotsAPI {
/*Retrofit get annotation with our URL
And our method that will return a Json Object
*/
#GET(url)
void getSlots(Callback<JsonElement> callback);
}
With this the call will be asynchronous.
Same problem here, and answer from curiousMind saved my day.
More on the same subject: if you need to get a value from a pair use:
String value = response.body().getAsJsonObject().get("pair_name").getAsString();
Call<Void> getSlots() worked for me.
private void APIRetrofit_method() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(RecyclerInterface.JSONURL)
// .client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
RecyclerInterface api = retrofit.create(RecyclerInterface.class);
Call<ResponseBody> call = api.getString(); /// GET METHOD without passing params
// Post METHOD CODE START
// HashMap<String, String> params = new HashMap<String, String>();
// params.put("name", "yuva");
// params.put("pass", "" + "123");
// Call<ResponseBody> call1 = api.getProspectList(params);
// Post METHOD CODE END
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
Log.d(TAG, "GetProspectlistresponse" + "" + response.isSuccessful());
utility.hideProgressDialog();
if (response.isSuccessful()) {
String remoteResponse = new String(response.body().string());
Log.d(TAG, "Holidaylistresponse" + "" + remoteResponse);
try {
JSONObject object = new JSONObject(remoteResponse);
JSONArray array = object.getJSONArray("Holidays_Details");
if (array.toString().equals("[]")) {
holiday_recyclerView.setVisibility(View.GONE);
} else {
holiday_recyclerView.setVisibility(View.VISIBLE);
for (int i = 0; i < array.length(); i++) {
JSONObject c = array.getJSONObject(i);
String holidayDate = c.getString(TAG_HOLIDAYDATE);
String holidayName = c.getString(TAG_HOLIDAYName);
String holidaytype = c.getString(TAG_HOLIDAYtype);
HashMap<String, String> customers = new HashMap<String, String>();
customers.put(TAG_HOLIDAYDATE, holidayDate);
customers.put(TAG_HOLIDAYName, holidayName);
customers.put(TAG_HOLIDAYtype, holidaytype);
arrayList.add(customers);
}
getHolidaylistAdapter.notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
utility.hideProgressDialog();
}
} catch (IOException e) {
e.printStackTrace();
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.i("ErrorResponsestring", call.toString());
}
});
}
String JSONURL = "https://demonuts.com/Demonuts/JsonTest/Tennis/";
#GET("json_parsing.php")
Call<ResponseBody> getString();
// #POST("getProspectList")
// #FormUrlEncoded
// Call<ResponseBody> getProspectList(#FieldMap HashMap<String, String> body);
implementation 'com.squareup.retrofit2:retrofit:2.0.2'
implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
implementation 'com.squareup.okhttp3:okhttp:4.0.0'