I have to work with an API which using JSend format.
Long story short it is using HTTP status codes which indicates status like:
- 200 is Success
- 406 is Unauthorized
Which is good because I can determine from this whether my API request is succeed or not.
BUT:
As JSend format has it's own thing, it has ALSO have a little status indicator at response just like this:
{
status : "success",
data : { "post" : { "id" : 2, "title" : "Another blog post", "body" : "More content" }}
}
So it has a 'status' field which ALSO shows whether the API request is succeed or not.
PROBLEM:
Retrofit made to parse the response to POJO so it assumes that the responses contains ONLY the Model and no indicators for success, just like this for example: (A post Model instance)
{ "id" : 2, "title" : "Another blog post", "body" : "More content" }
My question is:
Is there a solution for this?
Can I pre-parse the status indicators, split the 'data' (Model) part of the response and give it to retrofit for parse only that part?
If not I would have to add a "status" attribute to each of my models which is clearly not a walkable way, I won't do that.
Should I just stick with manual parsing and use ResponseBody
instead of my Models at
void onResponse(Call<T> call, Response<T> response);
for T
type paramter?
Because in that way I can use .string()
and convert the string to JSON and after that I can parse my Models manually like writing the parser for them.
I would really like to use Retrofit's feature for automatic parsing because with JSend I just cannot imagine how could be this properly done if anyhow at all.
I cannot change the API it's going to be this way.
Here is my Response
class.
public class Response<T> implements Serializable {
private T data;
private String status;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
Here is my api call.
Callback<com.shippn.api.models.Response<T>> callback = new Callback<com.shippn.api.models.Response<T>>() {
@Override
public void onResponse(Call<com.shippn.api.models.Response<T>> call, Response<com.shippn.api.models.Response<T>> response) {
checkStatus(response.body());
}
@Override
public void onFailure(Call<com.shippn.api.models.Response<T>> call, Throwable t) {
fail();
}
};
call.enqueue(callback);
T
parameter is type of your data from api. I mean if you want to get data in Post
type put Post
insted of T
. If you want to get ArrayList<Post>
put ArrayList<Post>
.
If data
field is empty or null in your api response, Response.data
will be null or empty, it wont throw an exception.
When you get response from api, first check Response.status
if it is "success" or not. If it is "success" get data from Response
, if it is not take your error actions.
One possible way is to create a wrapper for your models like
public class Example<T> {
String status;
T data;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
What you can do is you can have the status of the post request without using this.
The problem is that the parameter names are not string and will not be parsed in POJO.But you can get the status of you request like this.
@Override
public void onResponse(Call<Object> call, retrofit2.Response<Object> response) {
alertDialog.dismiss();
if (response.isSuccessful() && response.body() != null) {
//if the response is received here it means it was success
}else if(response.errorBody()!=null){
//if the response is received here it means it was error
}
}
@Override
public void onFailure(Call<Object> call, Throwable t) {
//if the response is received here it means it was failure
t.printStackTrace();
}
});
EDIT
In this way you can have the status with using pojo and you can parse the error simply as in this link
EDIT 1
Moreover for getting the proper error code you can extend your callback class to a class like
public class ErrorValues {
public int code=0;
public String error;
}
Then if the request was completed with a error.Inside
else if(response.errorBody()!=null){
int error=response.body.code == 404 ....
}
Like this you can check which error code was thrown by the request.