Today I got to know that Retrofit uses gson(or any other convertor) to serialize or deserialize the json response (response that was got using okhttp or any related library).
Now, when I was naive(in some sense still am) and I used to use Volley and at that time I never used Gson or any related library and same for okhttp.But i used to get my response and inflate it successfully on my views.
1. Now does Volley internally do what Retrofit does using Gson and Okhttp?
If not? 2. Then how did i able to get values parsed without using anything?
Below is the sample Codes that i used to write:-
JsonObjectRequest jsonObjectRequest=new JsonObjectRequest(
Request.Method.POST, URL_THUMB, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray=response.getJSONArray("server_response");
for(int i=0;i<jsonArray.length();i++)
{
JSONObject jsonObject=(JSONObject)jsonArray.get(i);
String id=jsonObject.getString("id");
String artist_name=jsonObject.getString("artist_name");
String img_id=jsonObject.getString("img_id");
listId.add(id);
listArtistName.add(artist_name);
listImgID.add(img_id);
}
recyclerView.setAdapter(comedy_adapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}
);
and now just inflate these list values to my views.
Where did I go wrong? (I don't think I was wrong as things went well and code always run fine)
In your example you're parsing the response into JSON arrays and objects manually. Converters such as Gson let you parse the response into a variable of a custom object in a single line.
For example, if I have the following model:
public class Model {
private int id;
private String name;
}
I can parse a string response using the following code:
Model model = gson.fromJson(str, Model.class);
Otherwise, you have to do it manually, like what you're doing at the moment:
JSONObject jsonObject = response.getJSONObject("str");
int id = jsonObject.getInt("id");
String name = jsonObject.getString("name");
Model model = new Model(id, name);
In Retrofit 2 you don't even have to call fromJson - you simple receive the object you expect as an input parameter in onResponse. It's very useful when dealing with more complex models.
Related
I want to send parameters such as username and password.
I got an error like String cannot be converted to jsonobject.
I dont know what this happening.Anyone pls help me my code is:
JSONObject obj=new JSONObject();
try{
obj.put("username","test");
obj.put("password","test");
} catch (JSONException e) {
}
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
urlJsonObj, obj, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
} catch (JSONException e) {
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonObjReq,json_obj_req);
}
There is nothing wrong with the way you are creating JSONObject and putting values in it. Make sure the response received is Json, because your onResponse method accepts JSONObject. You could be receiving String value as response, which could not be converted to JSONObject.
It looks like your response is actually a string and not a json object i.e. {"object":"value"} but rather "object:value". You need to sniff your response via either Stetho, Fiddler or reenact your request via Postman (or Fiddler)
======================
This doesn't answer your question, but this will help you tremendously and make your life easier.
Highly recommend using Gson and Retrofit to make HTTP requests and parse Gson objects easily.
https://github.com/google/gson
http://square.github.io/retrofit/
I'm using Retrofit 2 to call API in Android App. I have a API, using POST, which have a String param in Query Tag. I do everything like doc suppose and I test this API successfully in Test Page. I can run another API correctly so the problem is not the way I use Retrofit 2.
Here is my interface:
#POST("/users/{userId}/get_list_friends")
Call<GetListFriendDataResponse> getListFriend(#Path("userId") int userId, #Query("list") String list, #Query("page") int page, #Query("size") int size, #Header("hash") String hash);
Here is my implementation:
ArrayList<String> id = new ArrayList<>();
id.add("4782947293");
JSONArray jsonArray = new JSONArray(id);
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("list", jsonArray);
} catch (JSONException e) {
e.printStackTrace();
}
String list = jsonObject.toString();
Log.e(TAG, "list: " + list);
apiInterface.getListFriend(21, list, 1,1,"AHHIGHTJGI").enqueue(new Callback<GetListFriendDataResponse>() {
#Override
public void onResponse(Call<GetListFriendDataResponse> call, Response<GetListFriendDataResponse> response) {
Log.e(TAG, " response code: "+ response.code());
}
#Override
public void onFailure(Call<GetListFriendDataResponse> call, Throwable t) {
}
});
I always get response code: 400 when use this API.
I'm focusing the "list" var. "list" is a JSON text but I wonder if method "jSon.toString()" is right to get a String from a JSONObject, which can using in Retrofit 2. List param form is:{"list":["12332"]} .
Please help me!
Questions
1) Why you are creating JSONObject and JSONArray on your own?
2) You are creating string using whatever you are creating json.
Eg: {list:["123","456"]}
you are trying pass whole json, I think, instead you need to pass just the array of string to the list key.
Request Sending
{
list:["123","456"]
}
suppose the above json is the request you want to send to server
Now, create model class goto http://jsonschema2pojo.org and paste your json and select json and gson at right side and click on preview.
It will show the classes to map you json to model. Use this model class to set the list to the key in your json
I found my problem. The JSON text contains some special character so I need to convert them to URL encode.
Correct request URL like this:
http://54.169.215.161:8080/users/29/add_friend?list=%7B%22list%22%3A%5B%2215536%22%5D%7D&platform=google
By using Retrofit 2, it uses the URL:
http://54.169.215.161:8080/users/29/add_friend?list={%22list%22:[%2215536%22]}&platform=google
So I get Bad Request Response code.
Retrofit 2 also provides method to convert char sequence to URL encode but it 's not enough. So I don't use Retrofit 's convert method by using this code: encode= true.
so my interface is:
#POST("/users/{userId}/get_list_friends")
Call<GetListFriendDataResponse> getListFriend(#Path("userId") int userId, #Query(value = "list",encoded = true) String list, #Query("page") int page, #Query("size") int size, #Header("hash") String hash);
And I manually convert JSON text to URL encode by code:
list = list.replace("{", "%7B");
list=list.replace("]", "%5D");
list=list.replace("[", "%5B");
list=list.replace(":", "%3A");
list=list.replace("}","%7D");
list = list.replace("\"", "%22");
That's all. Now I can get data by using API.
Suggestion: If u have the same problem, check the URL retrofit return in response and compare to correct URL to see special character, which is not converted to URL encode.
My web server returns JSON in the following form if successful (200 status code):
{"success":true,"data":{"user_id":"20","username":"Bob"}}
But if something went wrong (for example, if the username and password entered was too short in a form), it returns JSON in the following form (400 status code):
{"success":true,"errors":{"username":["Username too short"],"password":["Incorrect password","Password too short"]}}
How do I handle these two different responses in Retrofit? This is my code so far:
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(URL)
.build();
ApiEndpointInterface api = restAdapter.create(ApiEndpointInterface.class);
api.getToken('1', new Callback<DefaultResponse>() {
#Override
public void success(DefaultResponse json, Response response) {
//
}
#Override
public void failure(RetrofitError response) {
//
}
});
How do I handle these two differently structured JSON responses?
You need to do two things.
First, do not return a 400 from the server. as others have stated you actually have a successful response from the server, so you just need to parse the error on your end.
your server can return a flag indicating login success or failure.
After that, you can simply add the error model to your DefaultResponse model. like so
public class DefaultResponse {
public boolean success;
public DataModel data;
public ErrorModel errors;
public static class DataModel {
private String user_id;
private String username;
}
public static class ErrorModel { ... }
}
You will still need to handle instances where your server responds with statuses other than OK, but typically error responses from a server are simple plain text, like "bad request".. You could of course insert json if you wish which you could extract from RetrofitError.getMessage(), but GSON wouldn't parse that for you automatically. I hope this helps!
You should realize that actually both responses you posted are success from the network request perspective.
The failure status is for the request failure (Network connection error, 404, etc.) and not failure you return after trying to login the user in your backend.
You'll need to parse the result in success method and decide weather the internal result is success from your app logic perspective.
You should offcourse also handle failure().
if you get the JSON from your web service, which mean it's success.
so, in your success method, grab the JSON and handle it
for example, from your JSON format
#Override
public void success(DefaultResponse json, Response response) {
try {
JSONObject json = new JSONObject(json);
JSONObject data = json.get("data"); // if no "data" element, it will throw JSONException
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),"username to short",Toast.LENGTH_SHORT).show();
}
}
or you can use GSON to handle your JSON data
I need to pass Json in Post request using Retrofit. My Json looks like this:
{
"q": {
"reg": "IND",
"or": [
{
"duration": "12"
}
]
},
"sort": "recent"
}
I created pojo for above Json using jsonschema2pojo which is similar to this: RoomListing.java class
Now I need to make a post request. So I created an API
public interface RoomListingAPI {
#GET("/api/fetch")
void getRoomListing(#Header("x-parse-session-token") String
token, #Body RoomListing list);
}
Created a RestAdapter class
return new RestAdapter.Builder()
.setEndpoint(BASE_URL)
.build();
RoomListingAPI apiservice = restadapter.providesRestAdapter().create(RoomListingAPI.class);
Now I am little bit confused to send Json (Have a look at RoomListing.java) as post request and receive JSON in response ?
Any help would be appreciable.
Firstly, you need to change the annotation from #GET to #POST to do a POST request. Next, assuming you're using Retrofit 1.9.x, you need to do one of two things to get the resulting JSON response, depending on if you want a synchronous or asynchronous response:
Synchronous (on the current thread) - change void to be of the type of the pojo for the response, similar to how you've made your request object (e.g. ResponseType yourMethod(#Body RequestType object);
Asynchronous (on a different thread, with a callback) - add a Callback<ResponseType> to the end of the method, which will then be called on the successful, or unsuccessful, return of the request (e.g. void yourMethod(#Body RequestObject object, Callback<ResponseType> callback);
public interface RoomListingAPI {
#POST("/api/fetch")
void getRoomListing(#Header("x-parse-session-token") String
token, #Field("YOURFIELDNAME") String json);
}
//This method generates your json
private String 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("reg", "IND");
jsonObject1.put("or", jsonArray);
jsonRoot.put("q", jsonObject1);
jsonRoot.put("sort", "recent");
}catch (JSONException e){
e.printStackTrace();
}
return jsonRoot.toString();
}
RoomListingAPI apiservice = restadapter.providesRestAdapter().create(RoomListingAPI.class);
apiservice.getRoomListing("your_header_token",yourJSON())...
I hope you work but it should be something like this.
I have the following json formatted string that is returned from the web service:
{"Success":false,"Message":"This version is not supported"}
I am using the following code to invoke the web service:
AsyncHttpClient client = new AsyncHttpClient();
client.get("http://mywebsite/check/getcompatibilityinfo", new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
System.out.println(response);
}
});
The response contains the json string now I need to access the Success and the Message property. Is there any simple way to do it without using complicated third party libraries?
The JSONObject class is already available in your Android codebase (no 3rd party dependencies). Since your example uses normal (simple) JSON, you can use:
try {
JSONObject responseJSON = new JSONObject(response);
} catch (JSONException e) {
e.printStackTrace();
}
boolean success = responseJSON.getBoolean("Success");
String message = responseJSON.getString("Message");