This is not a duplicate question.
I am using Retrofit 2.0 and json for network tasks.
Also I am not using GSON to parse json instead I am using simple JsonObject and JsonArray to get model objects from json string.
Firstly guide me which retrofit converter must be used for above scenario.
Secondly, I am not able to get json string as response string.
I tried two approaches -
Approach 1 - I used Call< Void >. In this case the response.body() returns null though status code is 200.
Approach 2 - I used Call< ResponseBody >. In this case call.enqueue methods call 'on failure method' instead of 'onSuccess' and also the response body is null.
The status code is 200 in this case also.
Please suggest how to get the json string as response from retrofit 2.0.
you need to use JsonObject instead of Void or ResponseBody. Your code should be
Call<JsonObject> getCall = request.getDataCall();
getCall.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
}
});
Note : make sure you are using com.google.gson.JsonObject
Related
I'm new to using Retrofit for networking in Android. So far I have successfully written code that sends a String to a PHP server. The server is configured to take my string, which contains a system ID and a password ("systemid=id&password=password"). It may seem odd to append parameters via a String like this but this is the way I have to do it for this project. Anyway, on the server if the id and password sent to it match certain criteria, it's sends back a list of file locations. So far, I am getting the proper response back from the server. In other words 'response.getMessage()' returns 'OK.' But how can I get the list that the server is trying to send back? Here is my implementation so far.
Interface:
public interface ExampleClient {
#POST("login/fake_name.php")
Call<String> sendStringToServer(#Body String string);
}
Here is my code within the Activity:
private void sendRequestToServer(String str) {
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://www.example.com/")
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
PromoterKiosksClient client = retrofit.create(ExampleClient.class);
Call<List<String>> call = client.sendStringToServer(str);
call.enqueue(new Callback<Void>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
Log.d(TAG, response.toString());
Log.d(TAG, response.message());
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Toast.makeText(AdminActivity.this, "you suck! keep trying", Toast.LENGTH_SHORT).show();
}
});
}
Is there somewhere in onResponse() that I can do this or do I need a totally different implementation? Thanks in advance
You are looking for response.body() ? Do you get a JSON response from the server? If so you can use POJO to convert your response. Would you be able to share your response here? You can use POJO to convert your result and name it Result.java and set that as your return type.
private void sendRequestToServer(String str) {
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://www.example.com/")
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
PromoterKiosksClient client = retrofit.create(ExampleClient.class);
Call<Result> call = client.sendStringToServer(str);
call.enqueue(new Callback<Void>() {
#Override
public void onResponse(Call<Result> call, Response<Result> response) {
Log.d(TAG, response.toString());
Log.d(TAG, response.message());
response.body(); // have your all data
}
#Override
public void onFailure(Call<Result> call, Throwable t) {
Toast.makeText(AdminActivity.this, "you suck! keep trying", Toast.LENGTH_SHORT).show();
}
});
}
Call<User> vs. Call<ResponseBody> vs. Call<Void>
Most endpoints will be declared with a specific return type, like Call. In this case Retrofit will always take the response body and try to convert it to Java objects. Of course, this takes time, memory and processing power.
If you can live without the mapped Java objects, you should choose Call. This makes the raw response payload available to you, but skips the mapping to Java objects. With this option, you still have the chance to analyze the payload (e.g., JSON).
The most efficient way is Call because it not only skips the conversion to Java objects, it also ignores the response body payload. When the response body is very large (e.g., a large JSON or an image), you can save a little bit of extra time and battery consumption by using Call. Of course, this results in the body() method of your response object returning null.
A good example to look at Consuming an API with retrofit and RXJava
I am using retrofit to parse JSON. I'm getting an exception while parsing a JSON response. My response is dynamic means that when I'm getting a successful response the response key is successful, but when I'm getting a fail response it turns to an error. How can I parse that response?
When I'm getting a fail response it's giving me a proper result, but when I'm getting a successful response it's going to end in failure and gives me an exception that Expected JsonObject but was JsonPrimitive.
I had a similar problem where server returned sometimes a JsonObject and sometimes a JsonPrimitive. When JsonPrimitive was returned I got 200 OK but it still ends up in onFailure because the types differed ( It expected a JsonObject but found a JsonPrimitive ).
public final class JsonPrimitive extends JsonElement
public final class JsonObject extends JsonElement
The com.google.gson documentation states that booth JsonPrimitive and JsonObject extend JsonElement so why not do:
JsonObject jsonObject = createJsonObject();
Call<JsonElement> requestCall = SomeInterface.sendRequest(jsonObject);
requestCall.enqueue(new Callback<JsonElement>() {
#Override
public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
//Now when you get a JsonPrimitive it will still end up here because
//JsonPrimitive extends JsonElement
}
#Override
public void onFailure(Call<JsonElement> call, Throwable t) {
}
}
Jsonobject and jsonprimitive is different type each other .
JsonObject { "name":"John", "age":30, "car":null }
JsonPrimitive (string, number, boolean)
Your response model is wrong . try this .
http://www.jsonschema2pojo.org/
Your API response is String and you try to get JsonObject.
check your API in Postman and sure API response is JsonObject.
I am using Retrofit library (version 2.0.2 as of this writing).
I am making a GET call to a service which responds a big JSON object but I am only interested in one key:value pair in it.
How can I get just that instead of writing a whole new POJO class that matches the JSON response?
Example -
{
status_code: 34,
status_message: "The resource you requested could not be found.",
...,
...
}
I need only status code value (34 here).
Please note, I am just giving an example of this JSON object here. The real one I am dealing with is huge and I care about only one key:value pair in it.
Thanks in advance.
You can refer to the following:
#GET("/files/jsonsample.json")
Call<JsonObject> readJsonFromFileUri();
and
class MyStatus{
int status_code;
}
...
Retrofit retrofit2 = new Retrofit.Builder()
.baseUrl("http://...")
.addConverterFactory(GsonConverterFactory.create())
.build();
WebAPIService apiService = retrofit2.create(WebAPIService.class);
Call<JsonObject> jsonCall = apiService.readJsonFromFileUri();
jsonCall.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
String jsonString = response.body().toString();
Gson gson = new Gson();
MyStatus status = gson.fromJson(jsonString, MyStatus.class);
Log.i(LOG_TAG, String.valueOf(status.status_code));
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Log.e(LOG_TAG, t.toString());
}
});
...
Debug screenshot
I am using Retrofit to make an api call. The top level object is named depending on the query parameters of the request. For example, a request like this:
api.somewebsite.com/1.0/mix_info?mix_id=69
returns a response like this:
{"69":{
"mix_id":"69",
"mix_title":"A Title",
"mix_file":"https:example.com/mp3",
"mix_genres":"House,Pop",
"mix_dj_id":"57",
"number_votes":"390",
"station":"1"
}
}
Heres a screenie as well that kinda shows the format:
http://prnt.sc/axltcd
Basically, depending on the number passed into the url mix_id= query becomes the name of the top level json object returned in the response.
I was able to hack together something that kinda works:
I have a model Response class which has a member variable that is the top level object, and I use Retrofit's #SerializedName("69") to explicity set the name. This, of course, will only work for a request with the id of 69, otherwise the response returns null object.
It looks like this:
public class Response {
#SerializedName("69")
private _69 _69;
}
Anyway, I'm looking for a way to properly handle these oddly formatted responses. How would this be done?
You can receive your response as JsonElemen, convert it to JsonObject and get element by global variable which you was using for send request.
Response:
public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
JsonElement jsonElement = response.body();
JsonObject jObj= jsonElement.getAsJsonObject();
JsonObject number= jObj.get(CONSTANT_WHICH_YOU_USED_FOR_REQEST).getAsJsonObject();
}
Feel free to ask me if any.
I have a webservice call which response is plain text and no json. In the callback below, failure() always gets called even with successful responses because retrofit tries to parse the response as json.
new Callback<String>() {
#Override
public void success(String s, Response response) {
...
}
#Override
public void failure(RetrofitError error) {
...
}
});
The following error occurs:
retrofit.RetrofitError: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 16 path $
How can I tell retrofit, that the response is plain text and should not be treated as json?
You are using GsonConverter for deserializing and Gson fails to validate the response as Json format. thats why you are getting MalformedJsonException. You need to supply something like this StringConverter in your RestAdapter