问题
My server returns a basic JSON structure for all request like:
{
"success": false,
"data": {
"errors": {
"email": [
"This is not an email."
],
"password": [
"The password must be at least 6 characters."
]
}
}
}
Where success
can be true or false, and data can return a number of things, from errors
to data the app might need.
How can I handle this response (both success and error) using Retrofit?
What would need to be changed/added to my Retrofit API call?
Call<BasicResponse> call = apiService.login(emailString, passwordString);
call.enqueue(new Callback<BasicResponse>() {
@Override
public void onResponse(Call<BasicResponse> call, Response<BasicResponse> response) {
//
}
@Override
public void onFailure(Call<BasicResponse> call, Throwable t) {
//
}
});
回答1:
Essentially you'll want to work with your models. You have a couple of options here, but in the end it comes down to the response code of your api and how you structure your models.
Let's get the models out of the way first. One way you can deal with the object having an error or not is by including this as a field of your models. Say you have the error object:
public class Errors {
// ...
}
This represents the errors object in your json:
"errors": {
"email": [
"This is not an email."
],
"password": [
"The password must be at least 6 characters."
]
}
Now say you have a data object to represent the json object:
"data": {
"errors": {
"email": [
"This is not an email."
],
"password": [
"The password must be at least 6 characters."
]
}
}
You can simply have:
public class Data {
@SerializedName("success")
@Expose
private boolean success;
@SerializedName("errors")
@Expose
private Errors errors;
// Here you can then add other models, i.e:
// @SerializedName("user")
// @Expose
// private User user;
}
As you can see, you can then add the rest of the models to the Data
object. When the response is successful, errors
will be null and success
true. When the response is unsuccessful you'll have the opposite scenario. You can check this answer for more details and other ways to achieve this.
Now to the part where you handle the error response.
If your call succeeds you'll end up in the onResponse
call. This means that you'll have to check the value of Data.success
before you can start interacting with your objects. If false
you know you can access the errors
field without producing a NullPointerException
and if true
you know you have the data correctly retrieved.
onFailure
is only called when there's an exception in example socket timeout or serialising and deserialising the request.
回答2:
this is what you need Retrobomb, you can create a model with a list errors.
From server you can return a 422 Exception
@RetrobombMappings(
ErrorMapping(code = 422, errorType = ErrorMap::class)
)
@Headers("Content-Type: application/json")
@POST("/endpoint")
fun createFoo(@Body params: Map<String, String>): Completable
data class ErrorMap(@SerializedName("errors") val errors: ErrorMap.Error){
class Error(@SerializedName("email") val email: List<String>?,
@SerializedName("password") val password : List<String>?)
}
Errors will be easy to handle.
来源:https://stackoverflow.com/questions/41539217/how-to-handle-errors-with-retrofit